目录
移动应用开发——食斋 1
1项目介绍和基础架构 3
2使用的开发框架和资源库 3
2.1Material Design: 3
2.2litePal: 3
2.3Retrofit2: 3
2.4Rxjava 3
3功能叙述 4
3.1用户方面 4
3.1.1用户的注册和登录 4
3.1.2用户的切换和登出 5
3.1.3修改用户信息 5
3.2食谱方面 6
3.2.1搜索并查看食谱 6
3.2.2收藏中意的食谱 8
3.2.3创建本地食谱 9
3.3系统设置方面 10
3.3.1能够指纹登录软件 10
3.3.2自定义主题 10
3.3.3传感器 11
1项目介绍和基础架构
在现代生活中,越来越多的都市居民也开始崇尚居家做菜的理念。为了更好的服务这部分的群体,因此我们决定制作简洁方便的食谱应用为快节奏的都市工作者提供方便快捷的食谱汇总,能够更轻松的完成自己想要的菜品。并通过获取网络上的食谱资源来满足用户对选择范围的需求。用户可以通过应用来获取自己想要的食谱并进行收藏。
项目采用了 MVP 的架构。presenter 通过 view 和 model 接口的引用,来调用具体实现类实现的方法,这么做的好处是,业务结构清晰,且将来更换实现类更为方便。
2使用的开发框架和资源库
2.1Material Design:
由 Google 开发的设计语言,充满简练干净的风格。食谱的布局里使用了许多来自 Material Design 的控件。确定了食谱软件简洁的 ui 风格。
2.2litePal:
LitePal 是一款开源的 Android 数据库框架,采用对象关系映射(ORM)模式, 将常用的数据库功能进行封装。软件中,用户的账号信息都由 LItePal 来进行本地存储。
2.3Retrofit2:
Retrofit2 针对于 Android/Java 的、基于 okHttp 的、一种轻量级且安全的、并使用注解方式的网络请求框架。
Retrofit 使用注解方式,大大简化了我们的 URL 拼写形式,而且注解含义一目了然,简单易懂;本文转载自http://www.biyezuopin.vip/onews.asp?id=15218支持同步和异步执行,使得请求变得异常简单。
App 通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、
Header、Url 等信息,然后使用 OkHttp 完成请求操作,然后 OkHttp 将原始的结果交给 Retrofit,Retrofit 根据用户的需求对结果进行解析。
2.4Rxjava:
RxJava 是目前比较流行的多线程的编程方式,将原本复杂的 java 多线程调
用瀑布流的方式呈现出来,简洁易用。
package com.example.ado.cookbookuser.view;import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;import com.bumptech.glide.Glide;
import com.example.ado.cookbookuser.R;
import com.example.ado.cookbookuser.model.CreateCookBook;
import com.example.ado.cookbookuser.model.FavCookBook;
import com.example.ado.cookbookuser.model.User;import org.litepal.LitePal;
import org.litepal.crud.DataSupport;import java.io.File;
import java.io.IOException;import de.hdodenhof.circleimageview.CircleImageView;import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;import com.example.ado.cookbookuser.data.RecyclerItem;
import com.example.ado.cookbookuser.presenter.MainPresenter;
import com.example.ado.cookbookuser.view.Fragment.MainFragment;
import com.example.ado.cookbookuser.view.Interface.MainViewI;
import com.example.ado.cookbookuser.view.Interface.OnClickListener;
import com.example.ado.cookbookuser.view.adapter.MFragmentAdapter;
import com.example.ado.cookbookuser.view.adapter.MRecyclerAdapter;
import com.jwenfeng.library.pulltorefresh.BaseRefreshListener;
import com.jwenfeng.library.pulltorefresh.PullToRefreshLayout;import java.util.ArrayList;public class MainActivity extends BaseActivity implements NavigationView.OnNavigationItemSelectedListener,
View.OnClickListener,MainViewI
{private DrawerLayout drawerLayout; //侧边栏private NavigationView navigationView; //侧边栏导航栏private View navLayout; //侧边栏导航栏头部布局private Menu navMenu; //侧边栏导航栏菜单private CircleImageView navCircleImageView; //侧边栏导航栏头部布局的头像private TextView navUserName; //侧边栏导航栏头部布局的用户名private Toolbar toolbarMain; //MainActivity的toolbarprivate TextView quitUser; //退出登录按键private FloatingActionButton fabUser; //右下方用户按键private EditText searchEdit; //搜索栏private TabLayout tabLayout;private ArrayList<String>tabdata=new ArrayList<>();private MainPresenter mainPresenter;private ViewPager viewPager;private ArrayList<Fragment>fragments=new ArrayList<>();private MFragmentAdapter pagerAdapter;private MRecyclerAdapter recyclerAdapter;private RecyclerView recyclerView;private PullToRefreshLayout pullToRefreshLayout;private int position=0;private static final String TAG = "MainActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mainPresenter=new MainPresenter(this);//创建本地数据库LitePal.getDatabase();quitUser = findViewById(R.id.quit_user);toolbarMain = findViewById(R.id.toolbar_main);drawerLayout = findViewById(R.id.drawer_layout);navigationView = findViewById(R.id.nav_user_view);fabUser = findViewById(R.id.fab_user);navLayout = navigationView.getHeaderView(0);navCircleImageView = navLayout.findViewById(R.id.nav_user_headShot);navUserName = navLayout.findViewById(R.id.nav_user_name);navMenu = navigationView.getMenu();tabLayout=findViewById(R.id.tabLayout);searchEdit = findViewById(R.id.search_edit);initLayout();//设置按键监听quitUser.setOnClickListener(this);fabUser.setOnClickListener(this);navCircleImageView.setOnClickListener(this);navigationView.setNavigationItemSelectedListener(this);}@Overrideprotected void onStart() {super.onStart();initWidget();}@Overridepublic void onDestroy(){super.onDestroy();if(mainPresenter!=null){mainPresenter.destroy();mainPresenter=null;}}//初始化界面private void initLayout(){// 初始化用户数据库
// DataSupport.deleteAll(User.class);// DataSupport.deleteAll(CreateCookBook.class);//DataSupport.deleteAll(FavCookBook.class);
// String userForNowFile = getExternalCacheDir().getAbsolutePath() + File.separator + "userForNowFile.txt";
// File file = new File(userForNowFile);
// if (file.exists()){
// file.delete();
// try{
// file.createNewFile();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }//设置toolbarsetToolbar(toolbarMain);ActionBar actionBar = getSupportActionBar();if(actionBar!=null){actionBar.setHomeAsUpIndicator(R.drawable.menu);}//菜谱界面展示逻辑initTabData();initTab(tabdata);initViewPager();initTabListening();}//初始化控件private void initWidget(){//隐藏侧边栏drawerLayout.closeDrawers();searchEdit.setFocusableInTouchMode(false);searchEdit.setFocusable(false);setOnsearchEditClick();//登录状态if(BaseActivity.userForNow != null) {quitUser.setVisibility(View.VISIBLE);fabUser.show();byte[] userForNowHeadShot = BaseActivity.userForNow.getHeadShot();Bitmap bitmap = BitmapFactory.decodeByteArray(userForNowHeadShot,0,userForNowHeadShot.length);Glide.with(MainActivity.this).load(bitmap).into(navCircleImageView);navUserName.setText(BaseActivity.userForNow.getName());navMenu.findItem(R.id.nav_myFavorite).setVisible(true);navMenu.findItem(R.id.nav_myCookbook).setVisible(true);//navMenu.findItem(R.id.nav_setting).setVisible(true);navMenu.findItem(R.id.nav_switch).setVisible(true);///navMenu.findItem(R.id.nav_exit).setVisible(true);navMenu.findItem(R.id.nav_changePwd).setVisible(true);}else{quitUser.setVisibility(View.GONE);fabUser.hide();Glide.with(MainActivity.this).load(R.drawable.pic).into(navCircleImageView);navUserName.setText("未登录");navMenu.findItem(R.id.nav_myFavorite).setVisible(false);navMenu.findItem(R.id.nav_myCookbook).setVisible(false);//navMenu.findItem(R.id.nav_setting).setVisible(false);navMenu.findItem(R.id.nav_switch).setVisible(false);navMenu.findItem(R.id.nav_changePwd).setVisible(false);//navMenu.findItem(R.id.nav_exit).setVisible(false);}}public void initTabData() {tabdata.add("家常菜");tabdata.add("快手菜");tabdata.add("创意菜");tabdata.add("素菜");tabdata.add("凉菜");tabdata.add("烘焙");tabdata.add("面食");tabdata.add("汤");tabdata.add("自制调味料");}public void initTab(ArrayList<String>tabdata) {for(int i=0;i<tabdata.size();i++){tabLayout.addTab(tabLayout.newTab().setText(tabdata.get(i)));}}public void initViewPager() {viewPager=findViewById(R.id.MainViewPager);for(int i=0;i<9;i++){MainFragment fragment=new MainFragment();fragments.add(fragment);}pagerAdapter=new MFragmentAdapter(fragments,getSupportFragmentManager(),tabdata);viewPager.setAdapter(pagerAdapter);tabLayout.setupWithViewPager(viewPager);mainPresenter.GetAndSetMovieData(Integer.toString(((MainFragment)fragments.get(position)).getItems().size()), position+1);}public void initTabListening() {viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {@Overridepublic void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}@Overridepublic void onPageSelected(int pos) {position=pos;recyclerView = fragments.get(position).getView().findViewById(R.id.Frecyclerview);if(((MRecyclerAdapter)recyclerView.getAdapter()).getData().size()==0)mainPresenter.GetAndSetMovieData(Integer.toString(((MainFragment)fragments.get(position)).getItems().size()), position+1);else {setRecyclerItemClickListener();mainPresenter.setRecyclerlistener();}}@Overridepublic void onPageScrollStateChanged(int state) {}});}//切换主题模式private void switchTheme(){int currentNightMode = getResources().getConfiguration().uiMode& Configuration.UI_MODE_NIGHT_MASK;switch (currentNightMode) {case Configuration.UI_MODE_NIGHT_NO: {getDelegate().setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);// Night mode is not active, we're in day timebreak;}case Configuration.UI_MODE_NIGHT_YES:{getDelegate().setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);// Night mode is active, we're at night!break;}case Configuration.UI_MODE_NIGHT_UNDEFINED: {// We don't know what mode we're in, assume notnight}}startActivity(new Intent(this,MainActivity.class));overridePendingTransition(R.anim.fade_out,R.anim.fade_in);finish();}private void userOut(String title,String message){AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);builder.setTitle(title);builder.setMessage(message);builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {String userForNowFile = getExternalCacheDir().getAbsolutePath() + File.separator + "userForNowFile.txt";File file = new File(userForNowFile);if (file.exists()){file.delete();}try {file.createNewFile();} catch (IOException e) {e.printStackTrace();}BaseActivity.userForNow = null;Intent intent = new Intent(MainActivity.this,LoginActivity.class);startActivity(intent);}});builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {}});builder.show();}public void setOnsearchEditClick(){searchEdit.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Intent intent=new Intent(MainActivity.this,SearchActivity.class);startActivity(intent);}});}@Overridepublic void onClick(View v) {switch (v.getId()){case R.id.fab_user:{Intent intent = new Intent(MainActivity.this,UserActivity.class);startActivity(intent);break;}case R.id.quit_user:{userOut("退出登录","您确定要退出登录吗?");break;}case R.id.nav_user_headShot:{if(BaseActivity.userForNow == null){Intent intent = new Intent(MainActivity.this,LoginActivity.class);startActivity(intent);}else{Intent intent = new Intent(MainActivity.this,UserActivity.class);startActivity(intent);}break;}default:break;}}//nav_menu的点击事件@Overridepublic boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {switch(menuItem.getItemId()){case R.id.nav_myFavorite:{Intent intent = new Intent(this, CollectionCreateActivity.class);intent.putExtra("which","like");startActivity(intent);break;}case R.id.nav_myCookbook:{Intent intent = new Intent(this, CollectionCreateActivity.class);intent.putExtra("which","create");startActivity(intent);break;}case R.id.nav_setting:{Intent intent = new Intent(this,SettingActivity.class);startActivity(intent);break;}case R.id.nav_dark_theme:{switchTheme();break;}case R.id.nav_changePwd:{Intent intent = new Intent(this,ChangePwdActivity.class);startActivity(intent);break;}case R.id.nav_switch:{userOut("切换帐号","您确定要切换帐号吗?");break;}case R.id.nav_exit:{finish();break;}}return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {switch (item.getItemId()){case android.R.id.home:{drawerLayout.openDrawer(GravityCompat.START);break;}}return true;}@Overridepublic void setRecyclerItemData(ArrayList<RecyclerItem>data) {recyclerView=fragments.get(position).getView().findViewById(R.id.Frecyclerview);recyclerAdapter=(MRecyclerAdapter)recyclerView.getAdapter();recyclerAdapter.addData(data);recyclerAdapter.notifyDataSetChanged();setRecyclerItemClickListener();if (pullToRefreshLayout!=null)pullToRefreshLayout.finishLoadMore();}@Overridepublic void initRefrshListening(){pullToRefreshLayout=((MainFragment)fragments.get(position)).getPullToRefreshLayout();if(pullToRefreshLayout!=null){pullToRefreshLayout.setRefreshListener(new BaseRefreshListener() {@Overridepublic void refresh() {pullToRefreshLayout.finishRefresh();}@Overridepublic void loadMore() {mainPresenter.GetAndSetMovieData(Integer.toString(((MainFragment)fragments.get(position)).getItems().size()), position+1);}});}}@Overridepublic void setRecyclerItemClickListener(){recyclerAdapter=(MRecyclerAdapter)recyclerView.getAdapter();((MRecyclerAdapter)recyclerView.getAdapter()).setOnItemClickListener(new OnClickListener() {@Overridepublic void onItemClick(View view, int position) {ArrayList<RecyclerItem>list=recyclerAdapter.getData();ArrayList<String>listname=new ArrayList<>();for(int i=0;i<list.size();i++){listname.add(list.get(i).getDescription());}Intent intent=new Intent(MainActivity.this, StepActivity.class);intent.putExtra("name",recyclerAdapter.getData().get(position).getDescription());intent.putExtra("type","0");//代表使用请求menu的网络调用接口intent.putStringArrayListExtra("list",listname);intent.putExtra("position",Integer.toString(position));//Bundle bundle=new Bundle();//bundle.putInt("type",0);//bundle.putString("name",recyclerAdapter.getData().get(position).getDescription());//intent.putExtra("content",bundle);intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);startActivity(intent);}});}}