安卓APP
源码和设计
报告——仿淘宝水果商城[/caption] userBeans = userDao.queryForWhat("email", textEmail);
return userBeans.size() == 0; } /** * 验证两次输入的密码是否一致 * * @return */
public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 向数据库表插入数据 */ public
void insertUserIntoDB() { UserBean userBean = new UserBean(textUserName, textPassword, textEmail); userDao.insert(userBean); // 同时存到SP中 spu.putString(Constant.USER_NAME, textUserName); spu.putString(Constant.PASSWORD, textPassword); } /** * 查询表中所有数据 */ public void queryAll() { List userBeans = userDao.queryAll(); for (int i = 0; i < userBeans.size(); i++) { Log.d(TAG, "queryAll: " + userBeans.get(i).toString()); } } } HomeActivity类 public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { @BindView(R.id.
toolbar) Toolbar toolbar; @BindView(R.id.
btn_top) RadioButton btnTop; @BindView(R.id.btn_add) RadioButton btnAdd; @BindView(R.id.btn_all) RadioButton btnAll; @BindView(R.id.dock_radio_group) RadioGroup dockRadioGroup; @BindView(R.id.drawer_layout) DrawerLayout drawerLayout; @BindView(R.id.nav_
view) NavigationView navView; private static final String TAG = "HomeActivity"; ActionBar actionBar; Fragment fragment; FragmentManager manager = getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); SharedPreferenceUtil spu; private UserDao userDao; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); ButterKnife.bind(this); userDao = new UserDao(this); spu = SharedPreferenceUtil.getInstance(this); initView(); } /** * 初始化控件 */ public void initView() { // 工具栏 toolbar.setTitle(R.string.
app_name); setTitleCenter(toolbar); setSupportActionBar(toolbar); actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.icon_setting); } // 抽屉 ViewGroup.LayoutParams params = navView.getLayoutParams(); params.width = getResources().getDisplayMetrics().widthPixels / 2; navView.setLayoutParams(params); navView.setNavigationItemSelectedListener(this); // 抽屉中的header View headerView = navView.getHeaderView(0); TextView textUserName = headerView.findViewById(R.id.header_user_name); TextView textEmail = headerView.findViewById(R.id.header_email); textUserName.setText(spu.getString(Constant.USER_NAME)); textEmail.setText(getEmail()); // 默认加载置顶Fragment fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); } /** * 单选按钮监听器 用来切换Fragment * * @param view * @param isChanged */ @OnCheckedChanged({R.id.btn_add, R.id.btn_all, R.id.btn_top}) public void onCheckedChanged(CompoundButton view, boolean isChanged) { transaction = manager.beginTransaction(); switch (view.getId()) {
case R.id.btn_top: if (isChanged) { fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); Constant.PAGE_STATE = "top"; }
break; case R.id.btn_add: if (isChanged) { fragment = new AddFragment(); transaction.replace(R.id.view_pager, fragment, Constant.ADD_TAG); transaction.commit(); } break; case R.id.btn_all: if (isChanged) { fragment = new AllFragment(); transaction.replace(R.id.view_pager, fragment, Constant.LIST_TAG); transaction.commit(); Constant.PAGE_STATE = "all"; } break; default: break; } } /** * 获得登录用户的邮箱 * * @return */ public String getEmail() { List userBeans = userDao .queryByUserNameAndPassword(spu.getString(Constant.USER_NAME), spu.getString(Constant.PASSWORD)); return userBeans.get(0).getEmail(); } /** * 抽屉中菜单的点击事件 * * @param item * @return */ @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { drawerLayout.closeDrawers(); switch (item.getItemId()) { case R.id.nav_change_pwd: DialogUtil.editInfoDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_dismiss: DialogUtil.dismissDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_exit: spu.putBoolean(Constant.AUTO_LOGIN, false); Intent
intent = new Intent(HomeActivity.this, MainActivity.class); startActivity(intent); finish(); break; default: break; } return true; } /** * ToolBar的menu * * @param menu * @return */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar_menu, menu); setIconsVisible(menu, true); return true; } /** * 重写ToolBar上菜单点击事件 * 按照条件查找 * * @param item * @return */ @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.search_title: DialogUtil.searchTitleDialog(this); break; case R.id.search_content: DialogUtil.searchContentDialog(this); break; case R.id.search_category: DialogUtil.searchCategoryDialog(this); break; case
android.R.id.home: drawerLayout.openDrawer(GravityCompat.START); break; default: break; } return true; } /** * ToolBar标题居中 * * @param toolbar */ public void setTitleCenter(Toolbar toolbar) { String title = "title"; final CharSequence originalTitle = toolbar.getTitle(); toolbar.setTitle(title); for (int i = 0; i < toolbar.getChildCount(); i++) { View view = toolbar.getChildAt(i); if (view instanceof TextView) { TextView textView = (TextView) view; if (title.equals(textView.getText())) { textView.setGravity(Gravity.CENTER); Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT); params.gravity = Gravity.CENTER; textView.setLayoutParams(params); } } toolbar.setTitle(originalTitle); } } /** * menu显示图标 * * @param menu * @param flag */ private void setIconsVisible(Menu menu, boolean flag) { // 判断menu是否为空 if (menu != null) { try { // 如果不为空,就反射拿到menu的setOptionalIconsVisible方法 Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); // 暴力访问该方法 method.setAccessible(true); // 调用该方法显示icon method.invoke(menu, flag); } catch (Exception e) { e.printStackTrace(); } } } FindPwdActivity类 public class FindPwdActivity extends AppCompatActivity { @BindView(R.id.btn_confirm_find) Button btnConfirmFind; @BindView(R.id.btn_reset_find) Button btnResetFind; @BindView(R.id.edit_confirm_pwd_find) EditText editConfirmPwdFind; @BindView(R.id.edit_password_find) EditText editPasswordFind; @BindView(R.id.edit_email_find) EditText editEmailFind; @BindView(R.id.check_hide_pwd_find) CheckBox checkHidePwdFind; @BindView(R.id.check_hide_pwd_find2) CheckBox checkHidePwdFind2; private static final String TAG = "FindPwdActivity"; private UserDao userDao; private String textPassword; private String textConfirmPwd; private String textEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_find_pwd); ButterKnife.bind(this); userDao = new UserDao(this); } @OnClick({R.id.btn_confirm_find, R.id.btn_reset_find, R.id.check_hide_pwd_find, R.id.check_hide_pwd_find2}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_confirm_find: // 检查非空 if (isNotEmpty()) { // 获得用户输入 getEditText(); // 检查邮箱格式 if (checkEmail()) { // 检查两次输入的密码是否一致 if (comparePwd()) { // 更新密码 if (updatePwdFromDB()) { // 跳转登录界面 Intent intent = new Intent(FindPwdActivity.this, MainActivity.class); startActivity(intent); FindPwdActivity.this.finish(); } } else { Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱或密码不能为空", Toast.LENGTH_SHORT).show(); } break; case R.id.btn_reset_find: // 清空输入 editPasswordFind.setText(""); editConfirmPwdFind.setText(""); editEmailFind.setText(""); break; case R.id.check_hide_pwd_find: if (checkHidePwdFind.isChecked()) { // 将密码显示出来 editPasswordFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editPasswordFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editPasswordFind.setSelection(editPasswordFind.getText().toString().length()); break; case R.id.check_hide_pwd_find2: if (checkHidePwdFind2.isChecked()) { // 将密码显示出来 editConfirmPwdFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editConfirmPwdFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editConfirmPwdFind.setSelection(editConfirmPwdFind.getText().toString().length()); break; default: break; } } /** * 检验输入非空 * * @return */ public boolean isNotEmpty() { return !"".equals(editPasswordFind.getText().toString()) && !"".equals(editConfirmPwdFind.getText().toString()) && !"".equals(editEmailFind.getText().toString()); } /** * 从控件中得到输入值 */ public void getEditText() { textPassword = editPasswordFind.getText().toString(); textConfirmPwd = editConfirmPwdFind.getText().toString(); textEmail = editEmailFind.getText().toString(); Log.d(TAG, "getEditText: " + textEmail); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 修改数据库中的密码 * * @return 邮箱是否存在 */ public boolean updatePwdFromDB() { List userBeans = userDao.queryForWhat("email", textEmail); if (userBeans.size() != 0) { UserBean user = userBeans.get(0); user.setPassword(textPassword); userDao.update(user); return true; } else { Toast.makeText(this, "邮箱错误", Toast.LENGTH_SHORT).show(); return false; } } } } public void onLeaveApplication(Ad arg0) { // TODO Auto-generated method stub } public void onFailedToReceiveAd(Ad arg0, ErrorCode arg1) { // TODO Auto-generated method stub } public void onDismissScreen(Ad arg0) { // TODO Auto-generated method stub } }); View gameMessage = findViewById(R.id.GameMessage); int[] data = getSettingData(); TextView levelMessage = (TextView)findViewById(R.id.level_Message); levelMessage.setText("SCORE: "+data[0]+"\nBEST: "+data[1]); gameMessage.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Intent intent = new Intent(LoadingActivity.this, GameBirdActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); finish(); } }); } private int[] getSettingData() { SharedPreferences gb_settings = getSharedPreferences(GameBirdActivity.GameBirdSettingsFile, 0); int last = gb_settings.getInt(GameBirdActivity.Settings_LevelLast, 0); int top = gb_settings.getInt(GameBirdActivity.Settings_LevelTop, 0); return new int[]{last, top}; } public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { try{ GameBirdActivity.instance.finish(); }catch(Exception e){} finish(); System.exit(0); return true; } return super.onKeyDown(keyCode, event); } } 四 总结 1
00" title="目录 一 安卓应用程序开发背景3 1.1开发背景3 1.2开发环境4 二 安卓应用程序开发理论与方法4 三 记事本应用程序的设计与实现5 3.1 拟解决的问题及目标5 3.2 总体设计6 3.3 详细设计与编码实现6 四 总结23 一 安卓应用程序开发背景 1.1开发背景 1.智能手机的市场 (1)功能多样化的智能手机挑战全球PC出货量 移动互联网时代的来临,直接促进了搭载智能操作系统、具有强大扩展性的智能手机、平板电脑等移动终端产业的蓬勃发展。来自美国最大的风险投资机构KPCB的数据显示,全球智能手机出货量正在以远高于台式电脑、笔记本电脑出货量的速度快速增长,该机构预计2011年全球智能手机出货量将达到4.13亿,超过台式电脑与笔记本电脑出货量的总和。 (2)智能手机的用户使用数量正在高速增长。据市场调研机构Gartner信息,2011年全球智能手机的总出货量将会达到4.68亿部,相比2010年实现了57.7%的增长,而谷歌Android操作系统将会在今年之内成为全球最大的智能手机操作系统。另外,全球市场调研机构IDC预计未来5年中国手机市场上,智能手机替代传统功能手机的趋势将日益明显,未来5年中国智能手机市场复合增长率将达到34.1%,人们对IT设备智能化的向往是这一增长率能够实现的主要因素,并且与其他国家相比,中国智能手机市场的发展空间更加广阔。 (3)操作系统格局预测:Android有望成为智能手机市场主导力量 搭载Android操作系统的智能手机目前已经成为市场上最炙手可热的智能产品。来自美国市场研究机构Gartner的数据显示,Android操作系统所占的市场份额从2008年的0.5%急剧增长到2011年的15.94%。开放的源代码和零成本已经让Android在全世界范围内受到青睐并迅速获得了主要手机厂商和数百万软件开发者的支持,Gartner预计,未来Android系统的市场份额有望超过其他操作系统,从而成为全球第一大智能手机操作系统。 2.安卓手机介绍 安卓手机指的是用Android操作系统的手机。安卓(Android)是基于Linux内核的操作系统,是Google公司在2007年11月5日公布的手机操作系统。 同样都是手机上面用的智能系统,安卓的系统是新生系统,界面更为华丽,开源性更强,当然因为是新生系统,所以在第三方软件方面暂时还不太多。因此,安卓应用程序的需求还是很迫切的。 3.软件人才需求 据业内统计,目前国内的Android研发人才缺口至少30万。由于目前Android技术较新,无论是相关书籍、培训还是大学教育,都处于初级阶段,因此Android人才短期将供不应求。从长期来看,随着各种移动应用和手机游戏等内容需求日益增加,也将激励大中小型手机应用开发商加大对Android应用的开发力度,因此Android人才的就业前景也非常广泛。 综上所述,在这样的背景下,安卓有很强的生命力。同时,作为一个新生的系统,其应用程序目前并不多,安卓应用程序的需求还是很迫切的,安卓研发人才的缺口还很大。这些都促进了我们学习开发安卓应用程序。 1.2开发环境 安卓应用程序开发环境如下: ①jdk1.8 ②android studio 4.0 ③Android SDK 二 安卓应用程序开发理论与方法 ButterKnife ButterKnife 是一个专注于 Android 系统的 View 注入框架,以前总是要写很多 findViewById 来找到 View 对象,有了 ButterKnife 可以很轻松地省去这些步骤。使用 ButterKnife 对性能基本没有损失,因为 ButterKnife 用到的注解并不是在运行时反射的,而是在编译的时候生成新的 class。项目集成起来特别方便,使用起来也特别简单。 ButterKnife 的优势: 强大的 View 绑定和 Click 事件处理功能,简化代码,提升开发效率 方便地处理 Adapter 里的 ViewHolder 绑定问题 运行时不会影响 APP 效率,使用配置方便 代码清晰,可读性强 SharedPreferences SharedPreferences 是使用键值对的方式来存储数据的。当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。而且 SharedPreferences 还支持多种不同的数据类型存储。 SQLite + OrmLite SQLite 是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百 KB 的内存就足够了,因而特别适合在移动设备上使用。SQLite 不仅支持标准的 SQL 语法,还遵循了数据库的 ACID 事务,所以只要以前是用过其他的关系型数据库,就可以很快地上手 SQLite。 ORM(全称 Object Relation Mapping)叫做对象关系映射,是一种程序设计技术,用于实现面向对象编程语言中不同类型系统的数据之间的转换。它可以直接将 Bean 文件转换成数据库中的表,Bean 中的属性就是表的列,它将繁琐的数据库操作封装成一个 Dao 类,使用 Dao 类和 Bean 可以直接对数据库进行操作,大多数的方法参数只有一个 Bean 对象。 多线程编程 Handler + Message Handler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用 Handler 的 sendMessage()方法,而发出的消息经过一系列的辗转处理后,最终会传递到 Handler 的 handleMessage()方法中。 Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。除了 what 字段,Message 还可以使用 arg1 和 arg2 字段来携带一些整型数据,使用 obj 字段携带一个 Object 对象。 Glide Glide 是一款快速高效的开源 Android 媒体管理和图片加载框架,它将媒体解码、内存和磁盘缓存以及资源池打包成一个简单易用的界面。 Glide 支持抓取、解码和显示视频图片、图像和动态 gif。Glide 包括一个灵活的 API,允许开发人员插入几乎任何网络堆栈。默认情况下,Glide 使用了一个定制的基于 HttpUrlConnection 的堆栈,但也包含了可插入谷歌的 Volley 项目或 Square 的 OkHttp 库的实用程序库。 Glide 的主要功能是尽可能平滑快速地滚动任何类型的图像列表,但它也适用于几乎任何需要获取、调整大小和显示远程图像的情况。 RecyclerView 控件 RecyclerView 是一个增强版的 ListView,不仅可以轻松实现和 ListView 同样的效果,还优化了 ListView 中存在的各种不足之处。同时 RecyclerView 支持横向滚动和瀑布流布局 Fragment + ViewPager Fragment 是一种可以嵌入在 Activity 当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用得非常广泛。它和 Activity 同样都能包含布局,同样都有自己的生命周期。甚至可以理解成一个迷你的 Activity。 ViewPager 是 android 扩展包 v4 包中的类,这个类可以让用户左右切换当前的 view。ViewPager 类直接继承了 ViewGroup 类,因此它一个容器类,可以添加其他的 View 类 ViewPager 类需要一个 PagerAdapter 适配器类给它提供数据(类似 RecyclerView)。 ViewPager 经常和 Fragment 一起使用,并且官方还提供了专门的 FragmentPagerAdapter 类供 ViewPager 使用。 三 记事本应用程序的设计与实现 3.1 拟解决的问题及目标 一个简单的记事本应用,在人们繁忙的时候更快速的记笔记,程序要实现的目标有如下几个: 登录注册 笔记顶置 开始游戏笔记增删查改 3.2 总体设计 1、记事本操作流程 先注册一个账号,登录进去,可以添加笔记,编辑笔记,顶置笔记,查找笔记 3.3 详细设计与编码实现 记事本界面 注册界面 新建笔记界面 编辑界面 个人信息界面 核心代码如下: RegisterActivity类 public class RegisterActivity extends AppCompatActivity { @BindView(R.id.btn_register) Button btnRegister; @BindView(R.id.btn_reset) Button btnReset; @BindView(R.id.check_hide_pwd_reg) CheckBox checkHidePwdReg; @BindView(R.id.check_hide_pwd_reg2) CheckBox checkHidePwdReg2; @BindView(R.id.edit_username_reg) EditText editUsernameReg; @BindView(R.id.edit_confirm_pwd_reg) EditText editConfirmPwdReg; @BindView(R.id.edit_email_reg) EditText editEmailReg; @BindView(R.id.edit_password_reg) EditText editPasswordReg; SharedPreferenceUtil spu; private static final String TAG = "RegisterActivity"; private UserDao userDao; private String textUserName; private String textPassword; private String textConfirmPwd; private String textEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register); ButterKnife.bind(this); userDao = new UserDao(this); spu = SharedPreferenceUtil.getInstance(this); } @OnClick({R.id.btn_register, R.id.btn_reset, R.id.check_hide_pwd_reg, R.id.check_hide_pwd_reg2}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_register: // 检验非空 if (isNotEmpty()) { // 获得用户输入 getEditText(); // 检验密码 if (comparePwd()) { // 检查邮箱格式 if (checkEmail()) { // 检查邮箱是否可用 if (checkOnlyEmail()) { insertUserIntoDB(); queryAll(); Intent intent = new Intent(RegisterActivity.this, MainActivity.class); intent.putExtra(Constant.HAS_REGISTERED, true); startActivity(intent); finish(); } else { Toast.makeText(this, "邮箱已经被使用", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show(); } break; case R.id.btn_reset: editUsernameReg.setText(""); editPasswordReg.setText(""); editConfirmPwdReg.setText(""); editEmailReg.setText(""); break; case R.id.check_hide_pwd_reg: if (checkHidePwdReg.isChecked()) { // 将密码显示出来 editPasswordReg.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editPasswordReg.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editPasswordReg.setSelection(editPasswordReg.getText().toString().length()); break; case R.id.check_hide_pwd_reg2: if (checkHidePwdReg2.isChecked()) { // 将密码显示出来 editConfirmPwdReg.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editConfirmPwdReg.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editConfirmPwdReg.setSelection(editConfirmPwdReg.getText().toString().length()); break; default: break; } } /** * 检验输入非空 * * @return */ public boolean isNotEmpty() { return !"".equals(editUsernameReg.getText().toString()) && !"".equals(editPasswordReg.getText().toString()) && !"".equals(editConfirmPwdReg.getText().toString()); } /** * 从控件中得到输入值 */ public void getEditText() { textUserName = editUsernameReg.getText().toString(); textPassword = editPasswordReg.getText().toString(); textConfirmPwd = editConfirmPwdReg.getText().toString(); textEmail = editEmailReg.getText().toString(); } /** * 检查邮箱是否可用 * * @return */ public boolean checkOnlyEmail() { List userBeans = userDao.queryForWhat("email", textEmail); return userBeans.size() == 0; } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 向数据库表插入数据 */ public void insertUserIntoDB() { UserBean userBean = new UserBean(textUserName, textPassword, textEmail); userDao.insert(userBean); // 同时存到SP中 spu.putString(Constant.USER_NAME, textUserName); spu.putString(Constant.PASSWORD, textPassword); } /** * 查询表中所有数据 */ public void queryAll() { List userBeans = userDao.queryAll(); for (int i = 0; i < userBeans.size(); i++) { Log.d(TAG, "queryAll: " + userBeans.get(i).toString()); } } } HomeActivity类 public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.btn_top) RadioButton btnTop; @BindView(R.id.btn_add) RadioButton btnAdd; @BindView(R.id.btn_all) RadioButton btnAll; @BindView(R.id.dock_radio_group) RadioGroup dockRadioGroup; @BindView(R.id.drawer_layout) DrawerLayout drawerLayout; @BindView(R.id.nav_view) NavigationView navView; private static final String TAG = "HomeActivity"; ActionBar actionBar; Fragment fragment; FragmentManager manager = getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); SharedPreferenceUtil spu; private UserDao userDao; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); ButterKnife.bind(this); userDao = new UserDao(this); spu = SharedPreferenceUtil.getInstance(this); initView(); } /** * 初始化控件 */ public void initView() { // 工具栏 toolbar.setTitle(R.string.app_name); setTitleCenter(toolbar); setSupportActionBar(toolbar); actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.icon_setting); } // 抽屉 ViewGroup.LayoutParams params = navView.getLayoutParams(); params.width = getResources().getDisplayMetrics().widthPixels / 2; navView.setLayoutParams(params); navView.setNavigationItemSelectedListener(this); // 抽屉中的header View headerView = navView.getHeaderView(0); TextView textUserName = headerView.findViewById(R.id.header_user_name); TextView textEmail = headerView.findViewById(R.id.header_email); textUserName.setText(spu.getString(Constant.USER_NAME)); textEmail.setText(getEmail()); // 默认加载置顶Fragment fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); } /** * 单选按钮监听器 用来切换Fragment * * @param view * @param isChanged */ @OnCheckedChanged({R.id.btn_add, R.id.btn_all, R.id.btn_top}) public void onCheckedChanged(CompoundButton view, boolean isChanged) { transaction = manager.beginTransaction(); switch (view.getId()) { case R.id.btn_top: if (isChanged) { fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); Constant.PAGE_STATE = "top"; } break; case R.id.btn_add: if (isChanged) { fragment = new AddFragment(); transaction.replace(R.id.view_pager, fragment, Constant.ADD_TAG); transaction.commit(); } break; case R.id.btn_all: if (isChanged) { fragment = new AllFragment(); transaction.replace(R.id.view_pager, fragment, Constant.LIST_TAG); transaction.commit(); Constant.PAGE_STATE = "all"; } break; default: break; } } /** * 获得登录用户的邮箱 * * @return */ public String getEmail() { List userBeans = userDao .queryByUserNameAndPassword(spu.getString(Constant.USER_NAME), spu.getString(Constant.PASSWORD)); return userBeans.get(0).getEmail(); } /** * 抽屉中菜单的点击事件 * * @param item * @return */ @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { drawerLayout.closeDrawers(); switch (item.getItemId()) { case R.id.nav_change_pwd: DialogUtil.editInfoDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_dismiss: DialogUtil.dismissDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_exit: spu.putBoolean(Constant.AUTO_LOGIN, false); Intent intent = new Intent(HomeActivity.this, MainActivity.class); startActivity(intent); finish(); break; default: break; } return true; } /** * ToolBar的menu * * @param menu * @return */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar_menu, menu); setIconsVisible(menu, true); return true; } /** * 重写ToolBar上菜单点击事件 * 按照条件查找 * * @param item * @return */ @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.search_title: DialogUtil.searchTitleDialog(this); break; case R.id.search_content: DialogUtil.searchContentDialog(this); break; case R.id.search_category: DialogUtil.searchCategoryDialog(this); break; case android.R.id.home: drawerLayout.openDrawer(GravityCompat.START); break; default: break; } return true; } /** * ToolBar标题居中 * * @param toolbar */ public void setTitleCenter(Toolbar toolbar) { String title = "title"; final CharSequence originalTitle = toolbar.getTitle(); toolbar.setTitle(title); for (int i = 0; i < toolbar.getChildCount(); i++) { View view = toolbar.getChildAt(i); if (view instanceof TextView) { TextView textView = (TextView) view; if (title.equals(textView.getText())) { textView.setGravity(Gravity.CENTER); Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT); params.gravity = Gravity.CENTER; textView.setLayoutParams(params); } } toolbar.setTitle(originalTitle); } } /** * menu显示图标 * * @param menu * @param flag */ private void setIconsVisible(Menu menu, boolean flag) { // 判断menu是否为空 if (menu != null) { try { // 如果不为空,就反射拿到menu的setOptionalIconsVisible方法 Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); // 暴力访问该方法 method.setAccessible(true); // 调用该方法显示icon method.invoke(menu, flag); } catch (Exception e) { e.printStackTrace(); } } } FindPwdActivity类 public class FindPwdActivity extends AppCompatActivity { @BindView(R.id.btn_confirm_find) Button btnConfirmFind; @BindView(R.id.btn_reset_find) Button btnResetFind; @BindView(R.id.edit_confirm_pwd_find) EditText editConfirmPwdFind; @BindView(R.id.edit_password_find) EditText editPasswordFind; @BindView(R.id.edit_email_find) EditText editEmailFind; @BindView(R.id.check_hide_pwd_find) CheckBox checkHidePwdFind; @BindView(R.id.check_hide_pwd_find2) CheckBox checkHidePwdFind2; private static final String TAG = "FindPwdActivity"; private UserDao userDao; private String textPassword; private String textConfirmPwd; private String textEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_find_pwd); ButterKnife.bind(this); userDao = new UserDao(this); } @OnClick({R.id.btn_confirm_find, R.id.btn_reset_find, R.id.check_hide_pwd_find, R.id.check_hide_pwd_find2}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_confirm_find: // 检查非空 if (isNotEmpty()) { // 获得用户输入 getEditText(); // 检查邮箱格式 if (checkEmail()) { // 检查两次输入的密码是否一致 if (comparePwd()) { // 更新密码 if (updatePwdFromDB()) { // 跳转登录界面 Intent intent = new Intent(FindPwdActivity.this, MainActivity.class); startActivity(intent); FindPwdActivity.this.finish(); } } else { Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱或密码不能为空", Toast.LENGTH_SHORT).show(); } break; case R.id.btn_reset_find: // 清空输入 editPasswordFind.setText(""); editConfirmPwdFind.setText(""); editEmailFind.setText(""); break; case R.id.check_hide_pwd_find: if (checkHidePwdFind.isChecked()) { // 将密码显示出来 editPasswordFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editPasswordFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editPasswordFind.setSelection(editPasswordFind.getText().toString().length()); break; case R.id.check_hide_pwd_find2: if (checkHidePwdFind2.isChecked()) { // 将密码显示出来 editConfirmPwdFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editConfirmPwdFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editConfirmPwdFind.setSelection(editConfirmPwdFind.getText().toString().length()); break; default: break; } } /** * 检验输入非空 * * @return */ public boolean isNotEmpty() { return !"".equals(editPasswordFind.getText().toString()) && !"".equals(editConfirmPwdFind.getText().toString()) && !"".equals(editEmailFind.getText().toString()); } /** * 从控件中得到输入值 */ public void getEditText() { textPassword = editPasswordFind.getText().toString(); textConfirmPwd = editConfirmPwdFind.getText().toString(); textEmail = editEmailFind.getText().toString(); Log.d(TAG, "getEditText: " + textEmail); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 修改数据库中的密码 * * @return 邮箱是否存在 */ public boolean updatePwdFromDB() { List userBeans = userDao.queryForWhat("email", textEmail); if (userBeans.size() != 0) { UserBean user = userBeans.get(0); user.setPassword(textPassword); userDao.update(user); return true; } else { Toast.makeText(this, "邮箱错误", Toast.LENGTH_SHORT).show(); return false; } } } } public void onLeaveApplication(Ad arg0) { // TODO Auto-generated method stub } public void onFailedToReceiveAd(Ad arg0, ErrorCode arg1) { // TODO Auto-generated method stub } public void onDismissScreen(Ad arg0) { // TODO Auto-generated method stub } }); View gameMessage = findViewById(R.id.GameMessage); int[] data = getSettingData(); TextView levelMessage = (TextView)findViewById(R.id.level_Message); levelMessage.setText("SCORE: "+data[0]+"\nBEST: "+data[1]); gameMessage.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Intent intent = new Intent(LoadingActivity.this, GameBirdActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); finish(); } }); } private int[] getSettingData() { SharedPreferences gb_settings = getSharedPreferences(GameBirdActivity.GameBirdSettingsFile, 0); int last = gb_settings.getInt(GameBirdActivity.Settings_LevelLast, 0); int top = gb_settings.getInt(GameBirdActivity.Settings_LevelTop, 0); return new int[]{last, top}; } public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { try{ GameBirdActivity.instance.finish(); }catch(Exception e){} finish(); System.exit(0); return true; } return super.onKeyDown(keyCode, event); } } 四 总结 100" /> 目录 一 安卓应用程序开发背景3 1.1开发背景3 1.2开发环境4 二 安卓应用程序开发理论与方法4 三 记事本应用程序的设计与实现5 3.1 拟解决的问题及目标5 3.2 总体设计6 3.3 详细设计与编码实现6 四 总结23 一 安卓应用程序开发背景 1.1开发背景 1.智能手机的市场 (1)功能多样化的智能手机挑战全球PC出货量 移动互联网时代的来临,直接促进了搭载智能操作系统、具有强大扩展性的智能手机、平板电脑等移动终端产业的蓬勃发展。来自美国最大的风险投资机构KPCB的数据显示,全球智能手机出货量正在以远高于台式电脑、笔记本电脑出货量的速度快速增长,该机构预计2011年全球智能手机出货量将达到4.13亿,超过台式电脑与笔记本电脑出货量的总和。 (2)智能手机的用户使用数量正在高速增长。据市场调研机构Gartner信息,2011年全球智能手机的总出货量将会达到4.68亿部,相比2010年实现了57.7%的增长,而谷歌Android操作系统将会在今年之内成为全球最大的智能手机操作系统。另外,全球市场调研机构IDC预计未来5年中国手机市场上,智能手机替代传统功能手机的趋势将日益明显,未来5年中国智能手机市场复合增长率将达到34.1%,人们对IT设备智能化的向往是这一增长率能够实现的主要因素,并且与其他国家相比,中国智能手机市场的发展空间更加广阔。 (3)操作系统格局预测:Android有望成为智能手机市场主导力量 搭载Android操作系统的智能手机目前已经成为市场上最炙手可热的智能产品。来自美国市场研究机构Gartner的数据显示,Android操作系统所占的市场份额从2008年的0.5%急剧增长到2011年的15.94%。开放的源代码和零成本已经让Android在全世界范围内受到青睐并迅速获得了主要手机厂商和数百万软件开发者的支持,Gartner预计,未来Android系统的市场份额有望超过其他操作系统,从而成为全球第一大智能手机操作系统。 2.安卓手机介绍 安卓手机指的是用Android操作系统的手机。安卓(Android)是基于Linux内核的操作系统,是Google公司在2007年11月5日公布的手机操作系统。 同样都是手机上面用的智能系统,安卓的系统是新生系统,界面更为华丽,开源性更强,当然因为是新生系统,所以在第三方软件方面暂时还不太多。因此,安卓应用程序的需求还是很迫切的。 3.软件人才需求 据业内统计,目前国内的Android研发人才缺口至少30万。由于目前Android技术较新,无论是相关书籍、培训还是大学教育,都处于初级阶段,因此Android人才短期将供不应求。从长期来看,随着各种移动应用和手机游戏等内容需求日益增加,也将激励大中小型手机应用开发商加大对Android应用的开发力度,因此Android人才的就业前景也非常广泛。 综上所述,在这样的背景下,安卓有很强的生命力。同时,作为一个新生的系统,其应用程序目前并不多,安卓应用程序的需求还是很迫切的,安卓研发人才的缺口还很大。这些都促进了我们学习开发安卓应用程序。 1.2开发环境 安卓应用程序开发环境如下: ①jdk1.8 ②android studio 4.0 ③Android SDK 二 安卓应用程序开发理论与方法 ButterKnife ButterKnife 是一个专注于 Android 系统的 View 注入框架,以前总是要写很多 findViewById 来找到 View 对象,有了 ButterKnife 可以很轻松地省去这些步骤。使用 ButterKnife 对性能基本没有损失,因为 ButterKnife 用到的注解并不是在运行时反射的,而是在编译的时候生成新的 class。项目集成起来特别方便,使用起来也特别简单。 ButterKnife 的优势: 强大的 View 绑定和 Click 事件处理功能,简化代码,提升开发效率 方便地处理 Adapter 里的 ViewHolder 绑定问题 运行时不会影响 APP 效率,使用配置方便 代码清晰,可读性强 SharedPreferences SharedPreferences 是使用键值对的方式来存储数据的。当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。而且 SharedPreferences 还支持多种不同的数据类型存储。 SQLite + OrmLite SQLite 是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百 KB 的内存就足够了,因而特别适合在移动设备上使用。SQLite 不仅支持标准的 SQL 语法,还遵循了数据库的 ACID 事务,所以只要以前是用过其他的关系型数据库,就可以很快地上手 SQLite。 ORM(全称 Object Relation Mapping)叫做对象关系映射,是一种程序设计技术,用于实现面向对象编程语言中不同类型系统的数据之间的转换。它可以直接将 Bean 文件转换成数据库中的表,Bean 中的属性就是表的列,它将繁琐的数据库操作封装成一个 Dao 类,使用 Dao 类和 Bean 可以直接对数据库进行操作,大多数的方法参数只有一个 Bean 对象。 多线程编程 Handler + Message Handler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用 Handler 的 sendMessage()方法,而发出的消息经过一系列的辗转处理后,最终会传递到 Handler 的 handleMessage()方法中。 Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。除了 what 字段,Message 还可以使用 arg1 和 arg2 字段来携带一些整型数据,使用 obj 字段携带一个 Object 对象。 Glide Glide 是一款快速高效的开源 Android 媒体管理和图片加载框架,它将媒体解码、内存和磁盘缓存以及资源池打包成一个简单易用的界面。 Glide 支持抓取、解码和显示视频图片、图像和动态 gif。Glide 包括一个灵活的 API,允许开发人员插入几乎任何网络堆栈。默认情况下,Glide 使用了一个定制的基于 HttpUrlConnection 的堆栈,但也包含了可插入谷歌的 Volley 项目或 Square 的 OkHttp 库的实用程序库。 Glide 的主要功能是尽可能平滑快速地滚动任何类型的图像列表,但它也适用于几乎任何需要获取、调整大小和显示远程图像的情况。 RecyclerView 控件 RecyclerView 是一个增强版的 ListView,不仅可以轻松实现和 ListView 同样的效果,还优化了 ListView 中存在的各种不足之处。同时 RecyclerView 支持横向滚动和瀑布流布局 Fragment + ViewPager Fragment 是一种可以嵌入在 Activity 当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用得非常广泛。它和 Activity 同样都能包含布局,同样都有自己的生命周期。甚至可以理解成一个迷你的 Activity。 ViewPager 是 android 扩展包 v4 包中的类,这个类可以让用户左右切换当前的 view。ViewPager 类直接继承了 ViewGroup 类,因此它一个容器类,可以添加其他的 View 类 ViewPager 类需要一个 PagerAdapter 适配器类给它提供数据(类似 RecyclerView)。 ViewPager 经常和 Fragment 一起使用,并且官方还提供了专门的 FragmentPagerAdapter 类供 ViewPager 使用。 三 记事本应用程序的设计与实现 3.1 拟解决的问题及目标 一个简单的记事本应用,在人们繁忙的时候更快速的记笔记,程序要实现的目标有如下几个: 登录注册 笔记顶置 开始游戏笔记增删查改 3.2 总体设计 1、记事本操作流程 先注册一个账号,登录进去,可以添加笔记,编辑笔记,顶置笔记,查找笔记 3.3 详细设计与编码实现 记事本界面 注册界面 新建笔记界面 编辑界面 个人信息界面 核心代码如下: RegisterActivity类 public class RegisterActivity extends AppCompatActivity { @BindView(R.id.btn_register) Button btnRegister; @BindView(R.id.btn_reset) Button btnReset; @BindView(R.id.check_hide_pwd_reg) CheckBox checkHidePwdReg; @BindView(R.id.check_hide_pwd_reg2) CheckBox checkHidePwdReg2; @BindView(R.id.edit_username_reg) EditText editUsernameReg; @BindView(R.id.edit_confirm_pwd_reg) EditText editConfirmPwdReg; @BindView(R.id.edit_email_reg) EditText editEmailReg; @BindView(R.id.edit_password_reg) EditText editPasswordReg; SharedPreferenceUtil spu; private static final String TAG = "RegisterActivity"; private UserDao userDao; private String textUserName; private String textPassword; private String textConfirmPwd; private String textEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register); ButterKnife.bind(this); userDao = new UserDao(this); spu = SharedPreferenceUtil.getInstance(this); } @OnClick({R.id.btn_register, R.id.btn_reset, R.id.check_hide_pwd_reg, R.id.check_hide_pwd_reg2}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_register: // 检验非空 if (isNotEmpty()) { // 获得用户输入 getEditText(); // 检验密码 if (comparePwd()) { // 检查邮箱格式 if (checkEmail()) { // 检查邮箱是否可用 if (checkOnlyEmail()) { insertUserIntoDB(); queryAll(); Intent intent = new Intent(RegisterActivity.this, MainActivity.class); intent.putExtra(Constant.HAS_REGISTERED, true); startActivity(intent); finish(); } else { Toast.makeText(this, "邮箱已经被使用", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show(); } break; case R.id.btn_reset: editUsernameReg.setText(""); editPasswordReg.setText(""); editConfirmPwdReg.setText(""); editEmailReg.setText(""); break; case R.id.check_hide_pwd_reg: if (checkHidePwdReg.isChecked()) { // 将密码显示出来 editPasswordReg.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editPasswordReg.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editPasswordReg.setSelection(editPasswordReg.getText().toString().length()); break; case R.id.check_hide_pwd_reg2: if (checkHidePwdReg2.isChecked()) { // 将密码显示出来 editConfirmPwdReg.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editConfirmPwdReg.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editConfirmPwdReg.setSelection(editConfirmPwdReg.getText().toString().length()); break; default: break; } } /** * 检验输入非空 * * @return */ public boolean isNotEmpty() { return !"".equals(editUsernameReg.getText().toString()) && !"".equals(editPasswordReg.getText().toString()) && !"".equals(editConfirmPwdReg.getText().toString()); } /** * 从控件中得到输入值 */ public void getEditText() { textUserName = editUsernameReg.getText().toString(); textPassword = editPasswordReg.getText().toString(); textConfirmPwd = editConfirmPwdReg.getText().toString(); textEmail = editEmailReg.getText().toString(); } /** * 检查邮箱是否可用 * * @return */ public boolean checkOnlyEmail() { List userBeans = userDao.queryForWhat("email", textEmail); return userBeans.size() == 0; } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 向数据库表插入数据 */ public void insertUserIntoDB() { UserBean userBean = new UserBean(textUserName, textPassword, textEmail); userDao.insert(userBean); // 同时存到SP中 spu.putString(Constant.USER_NAME, textUserName); spu.putString(Constant.PASSWORD, textPassword); } /** * 查询表中所有数据 */ public void queryAll() { List userBeans = userDao.queryAll(); for (int i = 0; i < userBeans.size(); i++) { Log.d(TAG, "queryAll: " + userBeans.get(i).toString()); } } } HomeActivity类 public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.btn_top) RadioButton btnTop; @BindView(R.id.btn_add) RadioButton btnAdd; @BindView(R.id.btn_all) RadioButton btnAll; @BindView(R.id.dock_radio_group) RadioGroup dockRadioGroup; @BindView(R.id.drawer_layout) DrawerLayout drawerLayout; @BindView(R.id.nav_view) NavigationView navView; private static final String TAG = "HomeActivity"; ActionBar actionBar; Fragment fragment; FragmentManager manager = getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); SharedPreferenceUtil spu; private UserDao userDao; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); ButterKnife.bind(this); userDao = new UserDao(this); spu = SharedPreferenceUtil.getInstance(this); initView(); } /** * 初始化控件 */ public void initView() { // 工具栏 toolbar.setTitle(R.string.app_name); setTitleCenter(toolbar); setSupportActionBar(toolbar); actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.icon_setting); } // 抽屉 ViewGroup.LayoutParams params = navView.getLayoutParams(); params.width = getResources().getDisplayMetrics().widthPixels / 2; navView.setLayoutParams(params); navView.setNavigationItemSelectedListener(this); // 抽屉中的header View headerView = navView.getHeaderView(0); TextView textUserName = headerView.findViewById(R.id.header_user_name); TextView textEmail = headerView.findViewById(R.id.header_email); textUserName.setText(spu.getString(Constant.USER_NAME)); textEmail.setText(getEmail()); // 默认加载置顶Fragment fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); } /** * 单选按钮监听器 用来切换Fragment * * @param view * @param isChanged */ @OnCheckedChanged({R.id.btn_add, R.id.btn_all, R.id.btn_top}) public void onCheckedChanged(CompoundButton view, boolean isChanged) { transaction = manager.beginTransaction(); switch (view.getId()) { case R.id.btn_top: if (isChanged) { fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); Constant.PAGE_STATE = "top"; } break; case R.id.btn_add: if (isChanged) { fragment = new AddFragment(); transaction.replace(R.id.view_pager, fragment, Constant.ADD_TAG); transaction.commit(); } break; case R.id.btn_all: if (isChanged) { fragment = new AllFragment(); transaction.replace(R.id.view_pager, fragment, Constant.LIST_TAG); transaction.commit(); Constant.PAGE_STATE = "all"; } break; default: break; } } /** * 获得登录用户的邮箱 * * @return */ public String getEmail() { List userBeans = userDao .queryByUserNameAndPassword(spu.getString(Constant.USER_NAME), spu.getString(Constant.PASSWORD)); return userBeans.get(0).getEmail(); } /** * 抽屉中菜单的点击事件 * * @param item * @return */ @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { drawerLayout.closeDrawers(); switch (item.getItemId()) { case R.id.nav_change_pwd: DialogUtil.editInfoDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_dismiss: DialogUtil.dismissDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_exit: spu.putBoolean(Constant.AUTO_LOGIN, false); Intent intent = new Intent(HomeActivity.this, MainActivity.class); startActivity(intent); finish(); break; default: break; } return true; } /** * ToolBar的menu * * @param menu * @return */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar_menu, menu); setIconsVisible(menu, true); return true; } /** * 重写ToolBar上菜单点击事件 * 按照条件查找 * * @param item * @return */ @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.search_title: DialogUtil.searchTitleDialog(this); break; case R.id.search_content: DialogUtil.searchContentDialog(this); break; case R.id.search_category: DialogUtil.searchCategoryDialog(this); break; case android.R.id.home: drawerLayout.openDrawer(GravityCompat.START); break; default: break; } return true; } /** * ToolBar标题居中 * * @param toolbar */ public void setTitleCenter(Toolbar toolbar) { String title = "title"; final CharSequence originalTitle = toolbar.getTitle(); toolbar.setTitle(title); for (int i = 0; i < toolbar.getChildCount(); i++) { View view = toolbar.getChildAt(i); if (view instanceof TextView) { TextView textView = (TextView) view; if (title.equals(textView.getText())) { textView.setGravity(Gravity.CENTER); Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT); params.gravity = Gravity.CENTER; textView.setLayoutParams(params); } } toolbar.setTitle(originalTitle); } } /** * menu显示图标 * * @param menu * @param flag */ private void setIconsVisible(Menu menu, boolean flag) { // 判断menu是否为空 if (menu != null) { try { // 如果不为空,就反射拿到menu的setOptionalIconsVisible方法 Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); // 暴力访问该方法 method.setAccessible(true); // 调用该方法显示icon method.invoke(menu, flag); } catch (Exception e) { e.printStackTrace(); } } } FindPwdActivity类 public class FindPwdActivity extends AppCompatActivity { @BindView(R.id.btn_confirm_find) Button btnConfirmFind; @BindView(R.id.btn_reset_find) Button btnResetFind; @BindView(R.id.edit_confirm_pwd_find) EditText editConfirmPwdFind; @BindView(R.id.edit_password_find) EditText editPasswordFind; @BindView(R.id.edit_email_find) EditText editEmailFind; @BindView(R.id.check_hide_pwd_find) CheckBox checkHidePwdFind; @BindView(R.id.check_hide_pwd_find2) CheckBox checkHidePwdFind2; private static final String TAG = "FindPwdActivity"; private UserDao userDao; private String textPassword; private String textConfirmPwd; private String textEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_find_pwd); ButterKnife.bind(this); userDao = new UserDao(this); } @OnClick({R.id.btn_confirm_find, R.id.btn_reset_find, R.id.check_hide_pwd_find, R.id.check_hide_pwd_find2}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_confirm_find: // 检查非空 if (isNotEmpty()) { // 获得用户输入 getEditText(); // 检查邮箱格式 if (checkEmail()) { // 检查两次输入的密码是否一致 if (comparePwd()) { // 更新密码 if (updatePwdFromDB()) { // 跳转登录界面 Intent intent = new Intent(FindPwdActivity.this, MainActivity.class); startActivity(intent); FindPwdActivity.this.finish(); } } else { Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱或密码不能为空", Toast.LENGTH_SHORT).show(); } break; case R.id.btn_reset_find: // 清空输入 editPasswordFind.setText(""); editConfirmPwdFind.setText(""); editEmailFind.setText(""); break; case R.id.check_hide_pwd_find: if (checkHidePwdFind.isChecked()) { // 将密码显示出来 editPasswordFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editPasswordFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editPasswordFind.setSelection(editPasswordFind.getText().toString().length()); break; case R.id.check_hide_pwd_find2: if (checkHidePwdFind2.isChecked()) { // 将密码显示出来 editConfirmPwdFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editConfirmPwdFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editConfirmPwdFind.setSelection(editConfirmPwdFind.getText().toString().length()); break; default: break; } } /** * 检验输入非空 * * @return */ public boolean isNotEmpty() { return !"".equals(editPasswordFind.getText().toString()) && !"".equals(editConfirmPwdFind.getText().toString()) && !"".equals(editEmailFind.getText().toString()); } /** * 从控件中得到输入值 */ public void getEditText() { textPassword = editPasswordFind.getText().toString(); textConfirmPwd = editConfirmPwdFind.getText().toString(); textEmail = editEmailFind.getText().toString(); Log.d(TAG, "getEditText: " + textEmail); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 修改数据库中的密码 * * @return 邮箱是否存在 */ public boolean updatePwdFromDB() { List userBeans = userDao.queryForWhat("email", textEmail); if (userBeans.size() != 0) { UserBean user = userBeans.get(0); user.setPassword(textPassword); userDao.update(user); return true; } else { Toast.makeText(this, "邮箱错误", Toast.LENGTH_SHORT).show(); return false; } } } } public void onLeaveApplication(Ad arg0) { // TODO Auto-generated method stub } public void onFailedToReceiveAd(Ad arg0, ErrorCode arg1) { // TODO Auto-generated method stub } public void onDismissScreen(Ad arg0) { // TODO Auto-generated method stub } }); View gameMessage = findViewById(R.id.GameMessage); int[] data = getSettingData(); TextView levelMessage = (TextView)findViewById(R.id.level_Message); levelMessage.setText("SCORE: "+data[0]+"\nBEST: "+data[1]); gameMessage.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Intent intent = new Intent(LoadingActivity.this, GameBirdActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); finish(); } }); } private int[] getSettingData() { SharedPreferences gb_settings = getSharedPreferences(GameBirdActivity.GameBirdSettingsFile, 0); int last = gb_settings.getInt(GameBirdActivity.Settings_LevelLast, 0); int top = gb_settings.getInt(GameBirdActivity.Settings_LevelTop, 0); return new int[]{last, top}; } public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { try{ GameBirdActivity.instance.finish(); }catch(Exception e){} finish(); System.exit(0); return true; } return super.onKeyDown(keyCode, event); } } 四 总结 100[/caption]userBeans = userDao.queryForWhat("email", textEmail); return userBeans.size() == 0; } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 向数据库表插入数据 */ public void insertUserIntoDB() { UserBean userBean = new UserBean(textUserName, textPassword, textEmail); userDao.insert(userBean); // 同时存到SP中 spu.putString(Constant.USER_NAME, textUserName); spu.putString(Constant.PASSWORD, textPassword); } /** * 查询表中所有数据 */ public void queryAll() { List userBeans = userDao.queryAll(); for (int i = 0; i < userBeans.size(); i++) { Log.d(TAG, "queryAll: " + userBeans.get(i).toString()); } } } HomeActivity类 public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.btn_top) RadioButton btnTop; @BindView(R.id.btn_add) RadioButton btnAdd; @BindView(R.id.btn_all) RadioButton btnAll; @BindView(R.id.dock_radio_group) RadioGroup dockRadioGroup; @BindView(R.id.drawer_layout) DrawerLayout drawerLayout; @BindView(R.id.nav_view) NavigationView navView; private static final String TAG = "HomeActivity"; ActionBar actionBar; Fragment fragment; FragmentManager manager = getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); SharedPreferenceUtil spu; private UserDao userDao; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); ButterKnife.bind(this); userDao = new UserDao(this); spu = SharedPreferenceUtil.getInstance(this); initView(); } /** * 初始化控件 */ public void initView() { // 工具栏 toolbar.setTitle(R.string.app_name); setTitleCenter(toolbar); setSupportActionBar(toolbar); actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.icon_setting); } // 抽屉 ViewGroup.LayoutParams params = navView.getLayoutParams(); params.width = getResources().getDisplayMetrics().widthPixels / 2; navView.setLayoutParams(params); navView.setNavigationItemSelectedListener(this); // 抽屉中的header View headerView = navView.getHeaderView(0); TextView textUserName = headerView.findViewById(R.id.header_user_name); TextView textEmail = headerView.findViewById(R.id.header_email); textUserName.setText(spu.getString(Constant.USER_NAME)); textEmail.setText(getEmail()); // 默认加载置顶Fragment fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); } /** * 单选按钮监听器 用来切换Fragment * * @param view * @param isChanged */ @OnCheckedChanged({R.id.btn_add, R.id.btn_all, R.id.btn_top}) public void onCheckedChanged(CompoundButton view, boolean isChanged) { transaction = manager.beginTransaction(); switch (view.getId()) { case R.id.btn_top: if (isChanged) { fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); Constant.PAGE_STATE = "top"; } break; case R.id.btn_add: if (isChanged) { fragment = new AddFragment(); transaction.replace(R.id.view_pager, fragment, Constant.ADD_TAG); transaction.commit(); } break; case R.id.btn_all: if (isChanged) { fragment = new AllFragment(); transaction.replace(R.id.view_pager, fragment, Constant.LIST_TAG); transaction.commit(); Constant.PAGE_STATE = "all"; } break; default: break; } } /** * 获得登录用户的邮箱 * * @return */ public String getEmail() { List userBeans = userDao .queryByUserNameAndPassword(spu.getString(Constant.USER_NAME), spu.getString(Constant.PASSWORD)); return userBeans.get(0).getEmail(); } /** * 抽屉中菜单的点击事件 * * @param item * @return */ @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { drawerLayout.closeDrawers(); switch (item.getItemId()) { case R.id.nav_change_pwd: DialogUtil.editInfoDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_dismiss: DialogUtil.dismissDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_exit: spu.putBoolean(Constant.AUTO_LOGIN, false); Intent intent = new Intent(HomeActivity.this, MainActivity.class); startActivity(intent); finish(); break; default: break; } return true; } /** * ToolBar的menu * * @param menu * @return */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar_menu, menu); setIconsVisible(menu, true); return true; } /** * 重写ToolBar上菜单点击事件 * 按照条件查找 * * @param item * @return */ @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.search_title: DialogUtil.searchTitleDialog(this); break; case R.id.search_content: DialogUtil.searchContentDialog(this); break; case R.id.search_category: DialogUtil.searchCategoryDialog(this); break; case android.R.id.home: drawerLayout.openDrawer(GravityCompat.START); break; default: break; } return true; } /** * ToolBar标题居中 * * @param toolbar */ public void setTitleCenter(Toolbar toolbar) { String title = "title"; final CharSequence originalTitle = toolbar.getTitle(); toolbar.setTitle(title); for (int i = 0; i < toolbar.getChildCount(); i++) { View view = toolbar.getChildAt(i); if (view instanceof TextView) { TextView textView = (TextView) view; if (title.equals(textView.getText())) { textView.setGravity(Gravity.CENTER); Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT); params.gravity = Gravity.CENTER; textView.setLayoutParams(params); } } toolbar.setTitle(originalTitle); } } /** * menu显示图标 * * @param menu * @param flag */ private void setIconsVisible(Menu menu, boolean flag) { // 判断menu是否为空 if (menu != null) { try { // 如果不为空,就反射拿到menu的setOptionalIconsVisible方法 Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); // 暴力访问该方法 method.setAccessible(true); // 调用该方法显示icon method.invoke(menu, flag); } catch (Exception e) { e.printStackTrace(); } } } FindPwdActivity类 public class FindPwdActivity extends AppCompatActivity { @BindView(R.id.btn_confirm_find) Button btnConfirmFind; @BindView(R.id.btn_reset_find) Button btnResetFind; @BindView(R.id.edit_confirm_pwd_find) EditText editConfirmPwdFind; @BindView(R.id.edit_password_find) EditText editPasswordFind; @BindView(R.id.edit_email_find) EditText editEmailFind; @BindView(R.id.check_hide_pwd_find) CheckBox checkHidePwdFind; @BindView(R.id.check_hide_pwd_find2) CheckBox checkHidePwdFind2; private static final String TAG = "FindPwdActivity"; private UserDao userDao; private String textPassword; private String textConfirmPwd; private String textEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_find_pwd); ButterKnife.bind(this); userDao = new UserDao(this); } @OnClick({R.id.btn_confirm_find, R.id.btn_reset_find, R.id.check_hide_pwd_find, R.id.check_hide_pwd_find2}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_confirm_find: // 检查非空 if (isNotEmpty()) { // 获得用户输入 getEditText(); // 检查邮箱格式 if (checkEmail()) { // 检查两次输入的密码是否一致 if (comparePwd()) { // 更新密码 if (updatePwdFromDB()) { // 跳转登录界面 Intent intent = new Intent(FindPwdActivity.this, MainActivity.class); startActivity(intent); FindPwdActivity.this.finish(); } } else { Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱或密码不能为空", Toast.LENGTH_SHORT).show(); } break; case R.id.btn_reset_find: // 清空输入 editPasswordFind.setText(""); editConfirmPwdFind.setText(""); editEmailFind.setText(""); break; case R.id.check_hide_pwd_find: if (checkHidePwdFind.isChecked()) { // 将密码显示出来 editPasswordFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editPasswordFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editPasswordFind.setSelection(editPasswordFind.getText().toString().length()); break; case R.id.check_hide_pwd_find2: if (checkHidePwdFind2.isChecked()) { // 将密码显示出来 editConfirmPwdFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editConfirmPwdFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editConfirmPwdFind.setSelection(editConfirmPwdFind.getText().toString().length()); break; default: break; } } /** * 检验输入非空 * * @return */ public boolean isNotEmpty() { return !"".equals(editPasswordFind.getText().toString()) && !"".equals(editConfirmPwdFind.getText().toString()) && !"".equals(editEmailFind.getText().toString()); } /** * 从控件中得到输入值 */ public void getEditText() { textPassword = editPasswordFind.getText().toString(); textConfirmPwd = editConfirmPwdFind.getText().toString(); textEmail = editEmailFind.getText().toString(); Log.d(TAG, "getEditText: " + textEmail); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 修改数据库中的密码 * * @return 邮箱是否存在 */ public boolean updatePwdFromDB() { List userBeans = userDao.queryForWhat("email", textEmail); if (userBeans.size() != 0) { UserBean user = userBeans.get(0); user.setPassword(textPassword); userDao.update(user); return true; } else { Toast.makeText(this, "邮箱错误", Toast.LENGTH_SHORT).show(); return false; } } } } public void onLeaveApplication(Ad arg0) { // TODO Auto-generated method stub } public void onFailedToReceiveAd(Ad arg0, ErrorCode arg1) { // TODO Auto-generated method stub } public void onDismissScreen(Ad arg0) { // TODO Auto-generated method stub } }); View gameMessage = findViewById(R.id.GameMessage); int[] data = getSettingData(); TextView levelMessage = (TextView)findViewById(R.id.level_Message); levelMessage.setText("SCORE: "+data[0]+"\nBEST: "+data[1]); gameMessage.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Intent intent = new Intent(LoadingActivity.this, GameBirdActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); finish(); } }); } private int[] getSettingData() { SharedPreferences gb_settings = getSharedPreferences(GameBirdActivity.GameBirdSettingsFile, 0); int last = gb_settings.getInt(GameBirdActivity.Settings_LevelLast, 0); int top = gb_settings.getInt(GameBirdActivity.Settings_LevelTop, 0); return new int[]{last, top}; } public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { try{ GameBirdActivity.instance.finish(); }catch(Exception e){} finish(); System.exit(0); return true; } return super.onKeyDown(keyCode, event); } } 四 总结 100" title="目录 一 安卓应用程序开发背景3 1.1开发背景3 1.2开发环境4 二 安卓应用程序开发理论与方法4 三 记事本应用程序的设计与实现5 3.1 拟解决的问题及目标5 3.2 总体设计6 3.3 详细设计与编码实现6 四 总结23 一 安卓应用程序开发背景 1.1开发背景 1.智能手机的市场 (1)功能多样化的智能手机挑战全球PC出货量 移动互联网时代的来临,直接促进了搭载智能操作系统、具有强大扩展性的智能手机、平板电脑等移动终端产业的蓬勃发展。来自美国最大的风险投资机构KPCB的数据显示,全球智能手机出货量正在以远高于台式电脑、笔记本电脑出货量的速度快速增长,该机构预计2011年全球智能手机出货量将达到4.13亿,超过台式电脑与笔记本电脑出货量的总和。 (2)智能手机的用户使用数量正在高速增长。据市场调研机构Gartner信息,2011年全球智能手机的总出货量将会达到4.68亿部,相比2010年实现了57.7%的增长,而谷歌Android操作系统将会在今年之内成为全球最大的智能手机操作系统。另外,全球市场调研机构IDC预计未来5年中国手机市场上,智能手机替代传统功能手机的趋势将日益明显,未来5年中国智能手机市场复合增长率将达到34.1%,人们对IT设备智能化的向往是这一增长率能够实现的主要因素,并且与其他国家相比,中国智能手机市场的发展空间更加广阔。 (3)操作系统格局预测:Android有望成为智能手机市场主导力量 搭载Android操作系统的智能手机目前已经成为市场上最炙手可热的智能产品。来自美国市场研究机构Gartner的数据显示,Android操作系统所占的市场份额从2008年的0.5%急剧增长到2011年的15.94%。开放的源代码和零成本已经让Android在全世界范围内受到青睐并迅速获得了主要手机厂商和数百万软件开发者的支持,Gartner预计,未来Android系统的市场份额有望超过其他操作系统,从而成为全球第一大智能手机操作系统。 2.安卓手机介绍 安卓手机指的是用Android操作系统的手机。安卓(Android)是基于Linux内核的操作系统,是Google公司在2007年11月5日公布的手机操作系统。 同样都是手机上面用的智能系统,安卓的系统是新生系统,界面更为华丽,开源性更强,当然因为是新生系统,所以在第三方软件方面暂时还不太多。因此,安卓应用程序的需求还是很迫切的。 3.软件人才需求 据业内统计,目前国内的Android研发人才缺口至少30万。由于目前Android技术较新,无论是相关书籍、培训还是大学教育,都处于初级阶段,因此Android人才短期将供不应求。从长期来看,随着各种移动应用和手机游戏等内容需求日益增加,也将激励大中小型手机应用开发商加大对Android应用的开发力度,因此Android人才的就业前景也非常广泛。 综上所述,在这样的背景下,安卓有很强的生命力。同时,作为一个新生的系统,其应用程序目前并不多,安卓应用程序的需求还是很迫切的,安卓研发人才的缺口还很大。这些都促进了我们学习开发安卓应用程序。 1.2开发环境 安卓应用程序开发环境如下: ①jdk1.8 ②android studio 4.0 ③Android SDK 二 安卓应用程序开发理论与方法 ButterKnife ButterKnife 是一个专注于 Android 系统的 View 注入框架,以前总是要写很多 findViewById 来找到 View 对象,有了 ButterKnife 可以很轻松地省去这些步骤。使用 ButterKnife 对性能基本没有损失,因为 ButterKnife 用到的注解并不是在运行时反射的,而是在编译的时候生成新的 class。项目集成起来特别方便,使用起来也特别简单。 ButterKnife 的优势: 强大的 View 绑定和 Click 事件处理功能,简化代码,提升开发效率 方便地处理 Adapter 里的 ViewHolder 绑定问题 运行时不会影响 APP 效率,使用配置方便 代码清晰,可读性强 SharedPreferences SharedPreferences 是使用键值对的方式来存储数据的。当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。而且 SharedPreferences 还支持多种不同的数据类型存储。 SQLite + OrmLite SQLite 是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百 KB 的内存就足够了,因而特别适合在移动设备上使用。SQLite 不仅支持标准的 SQL 语法,还遵循了数据库的 ACID 事务,所以只要以前是用过其他的关系型数据库,就可以很快地上手 SQLite。 ORM(全称 Object Relation Mapping)叫做对象关系映射,是一种程序设计技术,用于实现面向对象编程语言中不同类型系统的数据之间的转换。它可以直接将 Bean 文件转换成数据库中的表,Bean 中的属性就是表的列,它将繁琐的数据库操作封装成一个 Dao 类,使用 Dao 类和 Bean 可以直接对数据库进行操作,大多数的方法参数只有一个 Bean 对象。 多线程编程 Handler + Message Handler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用 Handler 的 sendMessage()方法,而发出的消息经过一系列的辗转处理后,最终会传递到 Handler 的 handleMessage()方法中。 Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。除了 what 字段,Message 还可以使用 arg1 和 arg2 字段来携带一些整型数据,使用 obj 字段携带一个 Object 对象。 Glide Glide 是一款快速高效的开源 Android 媒体管理和图片加载框架,它将媒体解码、内存和磁盘缓存以及资源池打包成一个简单易用的界面。 Glide 支持抓取、解码和显示视频图片、图像和动态 gif。Glide 包括一个灵活的 API,允许开发人员插入几乎任何网络堆栈。默认情况下,Glide 使用了一个定制的基于 HttpUrlConnection 的堆栈,但也包含了可插入谷歌的 Volley 项目或 Square 的 OkHttp 库的实用程序库。 Glide 的主要功能是尽可能平滑快速地滚动任何类型的图像列表,但它也适用于几乎任何需要获取、调整大小和显示远程图像的情况。 RecyclerView 控件 RecyclerView 是一个增强版的 ListView,不仅可以轻松实现和 ListView 同样的效果,还优化了 ListView 中存在的各种不足之处。同时 RecyclerView 支持横向滚动和瀑布流布局 Fragment + ViewPager Fragment 是一种可以嵌入在 Activity 当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用得非常广泛。它和 Activity 同样都能包含布局,同样都有自己的生命周期。甚至可以理解成一个迷你的 Activity。 ViewPager 是 android 扩展包 v4 包中的类,这个类可以让用户左右切换当前的 view。ViewPager 类直接继承了 ViewGroup 类,因此它一个容器类,可以添加其他的 View 类 ViewPager 类需要一个 PagerAdapter 适配器类给它提供数据(类似 RecyclerView)。 ViewPager 经常和 Fragment 一起使用,并且官方还提供了专门的 FragmentPagerAdapter 类供 ViewPager 使用。 三 记事本应用程序的设计与实现 3.1 拟解决的问题及目标 一个简单的记事本应用,在人们繁忙的时候更快速的记笔记,程序要实现的目标有如下几个: 登录注册 笔记顶置 开始游戏笔记增删查改 3.2 总体设计 1、记事本操作流程 先注册一个账号,登录进去,可以添加笔记,编辑笔记,顶置笔记,查找笔记 3.3 详细设计与编码实现 记事本界面 注册界面 新建笔记界面 编辑界面 个人信息界面 核心代码如下: RegisterActivity类 public class RegisterActivity extends AppCompatActivity { @BindView(R.id.btn_register) Button btnRegister; @BindView(R.id.btn_reset) Button btnReset; @BindView(R.id.check_hide_pwd_reg) CheckBox checkHidePwdReg; @BindView(R.id.check_hide_pwd_reg2) CheckBox checkHidePwdReg2; @BindView(R.id.edit_username_reg) EditText editUsernameReg; @BindView(R.id.edit_confirm_pwd_reg) EditText editConfirmPwdReg; @BindView(R.id.edit_email_reg) EditText editEmailReg; @BindView(R.id.edit_password_reg) EditText editPasswordReg; SharedPreferenceUtil spu; private static final String TAG = "RegisterActivity"; private UserDao userDao; private String textUserName; private String textPassword; private String textConfirmPwd; private String textEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register); ButterKnife.bind(this); userDao = new UserDao(this); spu = SharedPreferenceUtil.getInstance(this); } @OnClick({R.id.btn_register, R.id.btn_reset, R.id.check_hide_pwd_reg, R.id.check_hide_pwd_reg2}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_register: // 检验非空 if (isNotEmpty()) { // 获得用户输入 getEditText(); // 检验密码 if (comparePwd()) { // 检查邮箱格式 if (checkEmail()) { // 检查邮箱是否可用 if (checkOnlyEmail()) { insertUserIntoDB(); queryAll(); Intent intent = new Intent(RegisterActivity.this, MainActivity.class); intent.putExtra(Constant.HAS_REGISTERED, true); startActivity(intent); finish(); } else { Toast.makeText(this, "邮箱已经被使用", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show(); } break; case R.id.btn_reset: editUsernameReg.setText(""); editPasswordReg.setText(""); editConfirmPwdReg.setText(""); editEmailReg.setText(""); break; case R.id.check_hide_pwd_reg: if (checkHidePwdReg.isChecked()) { // 将密码显示出来 editPasswordReg.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editPasswordReg.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editPasswordReg.setSelection(editPasswordReg.getText().toString().length()); break; case R.id.check_hide_pwd_reg2: if (checkHidePwdReg2.isChecked()) { // 将密码显示出来 editConfirmPwdReg.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editConfirmPwdReg.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editConfirmPwdReg.setSelection(editConfirmPwdReg.getText().toString().length()); break; default: break; } } /** * 检验输入非空 * * @return */ public boolean isNotEmpty() { return !"".equals(editUsernameReg.getText().toString()) && !"".equals(editPasswordReg.getText().toString()) && !"".equals(editConfirmPwdReg.getText().toString()); } /** * 从控件中得到输入值 */ public void getEditText() { textUserName = editUsernameReg.getText().toString(); textPassword = editPasswordReg.getText().toString(); textConfirmPwd = editConfirmPwdReg.getText().toString(); textEmail = editEmailReg.getText().toString(); } /** * 检查邮箱是否可用 * * @return */ public boolean checkOnlyEmail() { List userBeans = userDao.queryForWhat("email", textEmail); return userBeans.size() == 0; } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 向数据库表插入数据 */ public void insertUserIntoDB() { UserBean userBean = new UserBean(textUserName, textPassword, textEmail); userDao.insert(userBean); // 同时存到SP中 spu.putString(Constant.USER_NAME, textUserName); spu.putString(Constant.PASSWORD, textPassword); } /** * 查询表中所有数据 */ public void queryAll() { List userBeans = userDao.queryAll(); for (int i = 0; i < userBeans.size(); i++) { Log.d(TAG, "queryAll: " + userBeans.get(i).toString()); } } } HomeActivity类 public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.btn_top) RadioButton btnTop; @BindView(R.id.btn_add) RadioButton btnAdd; @BindView(R.id.btn_all) RadioButton btnAll; @BindView(R.id.dock_radio_group) RadioGroup dockRadioGroup; @BindView(R.id.drawer_layout) DrawerLayout drawerLayout; @BindView(R.id.nav_view) NavigationView navView; private static final String TAG = "HomeActivity"; ActionBar actionBar; Fragment fragment; FragmentManager manager = getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); SharedPreferenceUtil spu; private UserDao userDao; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); ButterKnife.bind(this); userDao = new UserDao(this); spu = SharedPreferenceUtil.getInstance(this); initView(); } /** * 初始化控件 */ public void initView() { // 工具栏 toolbar.setTitle(R.string.app_name); setTitleCenter(toolbar); setSupportActionBar(toolbar); actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.icon_setting); } // 抽屉 ViewGroup.LayoutParams params = navView.getLayoutParams(); params.width = getResources().getDisplayMetrics().widthPixels / 2; navView.setLayoutParams(params); navView.setNavigationItemSelectedListener(this); // 抽屉中的header View headerView = navView.getHeaderView(0); TextView textUserName = headerView.findViewById(R.id.header_user_name); TextView textEmail = headerView.findViewById(R.id.header_email); textUserName.setText(spu.getString(Constant.USER_NAME)); textEmail.setText(getEmail()); // 默认加载置顶Fragment fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); } /** * 单选按钮监听器 用来切换Fragment * * @param view * @param isChanged */ @OnCheckedChanged({R.id.btn_add, R.id.btn_all, R.id.btn_top}) public void onCheckedChanged(CompoundButton view, boolean isChanged) { transaction = manager.beginTransaction(); switch (view.getId()) { case R.id.btn_top: if (isChanged) { fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); Constant.PAGE_STATE = "top"; } break; case R.id.btn_add: if (isChanged) { fragment = new AddFragment(); transaction.replace(R.id.view_pager, fragment, Constant.ADD_TAG); transaction.commit(); } break; case R.id.btn_all: if (isChanged) { fragment = new AllFragment(); transaction.replace(R.id.view_pager, fragment, Constant.LIST_TAG); transaction.commit(); Constant.PAGE_STATE = "all"; } break; default: break; } } /** * 获得登录用户的邮箱 * * @return */ public String getEmail() { List userBeans = userDao .queryByUserNameAndPassword(spu.getString(Constant.USER_NAME), spu.getString(Constant.PASSWORD)); return userBeans.get(0).getEmail(); } /** * 抽屉中菜单的点击事件 * * @param item * @return */ @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { drawerLayout.closeDrawers(); switch (item.getItemId()) { case R.id.nav_change_pwd: DialogUtil.editInfoDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_dismiss: DialogUtil.dismissDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_exit: spu.putBoolean(Constant.AUTO_LOGIN, false); Intent intent = new Intent(HomeActivity.this, MainActivity.class); startActivity(intent); finish(); break; default: break; } return true; } /** * ToolBar的menu * * @param menu * @return */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar_menu, menu); setIconsVisible(menu, true); return true; } /** * 重写ToolBar上菜单点击事件 * 按照条件查找 * * @param item * @return */ @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.search_title: DialogUtil.searchTitleDialog(this); break; case R.id.search_content: DialogUtil.searchContentDialog(this); break; case R.id.search_category: DialogUtil.searchCategoryDialog(this); break; case android.R.id.home: drawerLayout.openDrawer(GravityCompat.START); break; default: break; } return true; } /** * ToolBar标题居中 * * @param toolbar */ public void setTitleCenter(Toolbar toolbar) { String title = "title"; final CharSequence originalTitle = toolbar.getTitle(); toolbar.setTitle(title); for (int i = 0; i < toolbar.getChildCount(); i++) { View view = toolbar.getChildAt(i); if (view instanceof TextView) { TextView textView = (TextView) view; if (title.equals(textView.getText())) { textView.setGravity(Gravity.CENTER); Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT); params.gravity = Gravity.CENTER; textView.setLayoutParams(params); } } toolbar.setTitle(originalTitle); } } /** * menu显示图标 * * @param menu * @param flag */ private void setIconsVisible(Menu menu, boolean flag) { // 判断menu是否为空 if (menu != null) { try { // 如果不为空,就反射拿到menu的setOptionalIconsVisible方法 Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); // 暴力访问该方法 method.setAccessible(true); // 调用该方法显示icon method.invoke(menu, flag); } catch (Exception e) { e.printStackTrace(); } } } FindPwdActivity类 public class FindPwdActivity extends AppCompatActivity { @BindView(R.id.btn_confirm_find) Button btnConfirmFind; @BindView(R.id.btn_reset_find) Button btnResetFind; @BindView(R.id.edit_confirm_pwd_find) EditText editConfirmPwdFind; @BindView(R.id.edit_password_find) EditText editPasswordFind; @BindView(R.id.edit_email_find) EditText editEmailFind; @BindView(R.id.check_hide_pwd_find) CheckBox checkHidePwdFind; @BindView(R.id.check_hide_pwd_find2) CheckBox checkHidePwdFind2; private static final String TAG = "FindPwdActivity"; private UserDao userDao; private String textPassword; private String textConfirmPwd; private String textEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_find_pwd); ButterKnife.bind(this); userDao = new UserDao(this); } @OnClick({R.id.btn_confirm_find, R.id.btn_reset_find, R.id.check_hide_pwd_find, R.id.check_hide_pwd_find2}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_confirm_find: // 检查非空 if (isNotEmpty()) { // 获得用户输入 getEditText(); // 检查邮箱格式 if (checkEmail()) { // 检查两次输入的密码是否一致 if (comparePwd()) { // 更新密码 if (updatePwdFromDB()) { // 跳转登录界面 Intent intent = new Intent(FindPwdActivity.this, MainActivity.class); startActivity(intent); FindPwdActivity.this.finish(); } } else { Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱或密码不能为空", Toast.LENGTH_SHORT).show(); } break; case R.id.btn_reset_find: // 清空输入 editPasswordFind.setText(""); editConfirmPwdFind.setText(""); editEmailFind.setText(""); break; case R.id.check_hide_pwd_find: if (checkHidePwdFind.isChecked()) { // 将密码显示出来 editPasswordFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editPasswordFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editPasswordFind.setSelection(editPasswordFind.getText().toString().length()); break; case R.id.check_hide_pwd_find2: if (checkHidePwdFind2.isChecked()) { // 将密码显示出来 editConfirmPwdFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editConfirmPwdFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editConfirmPwdFind.setSelection(editConfirmPwdFind.getText().toString().length()); break; default: break; } } /** * 检验输入非空 * * @return */ public boolean isNotEmpty() { return !"".equals(editPasswordFind.getText().toString()) && !"".equals(editConfirmPwdFind.getText().toString()) && !"".equals(editEmailFind.getText().toString()); } /** * 从控件中得到输入值 */ public void getEditText() { textPassword = editPasswordFind.getText().toString(); textConfirmPwd = editConfirmPwdFind.getText().toString(); textEmail = editEmailFind.getText().toString(); Log.d(TAG, "getEditText: " + textEmail); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 修改数据库中的密码 * * @return 邮箱是否存在 */ public boolean updatePwdFromDB() { List userBeans = userDao.queryForWhat("email", textEmail); if (userBeans.size() != 0) { UserBean user = userBeans.get(0); user.setPassword(textPassword); userDao.update(user); return true; } else { Toast.makeText(this, "邮箱错误", Toast.LENGTH_SHORT).show(); return false; } } } } public void onLeaveApplication(Ad arg0) { // TODO Auto-generated method stub } public void onFailedToReceiveAd(Ad arg0, ErrorCode arg1) { // TODO Auto-generated method stub } public void onDismissScreen(Ad arg0) { // TODO Auto-generated method stub } }); View gameMessage = findViewById(R.id.GameMessage); int[] data = getSettingData(); TextView levelMessage = (TextView)findViewById(R.id.level_Message); levelMessage.setText("SCORE: "+data[0]+"\nBEST: "+data[1]); gameMessage.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Intent intent = new Intent(LoadingActivity.this, GameBirdActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); finish(); } }); } private int[] getSettingData() { SharedPreferences gb_settings = getSharedPreferences(GameBirdActivity.GameBirdSettingsFile, 0); int last = gb_settings.getInt(GameBirdActivity.Settings_LevelLast, 0); int top = gb_settings.getInt(GameBirdActivity.Settings_LevelTop, 0); return new int[]{last, top}; } public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { try{ GameBirdActivity.instance.finish(); }catch(Exception e){} finish(); System.exit(0); return true; } return super.onKeyDown(keyCode, event); } } 四 总结 100" /> 目录 一 安卓应用程序开发背景3 1.1开发背景3 1.2开发环境4 二 安卓应用程序开发理论与方法4 三 记事本应用程序的设计与实现5 3.1 拟解决的问题及目标5 3.2 总体设计6 3.3 详细设计与编码实现6 四 总结23 一 安卓应用程序开发背景 1.1开发背景 1.智能手机的市场 (1)功能多样化的智能手机挑战全球PC出货量 移动互联网时代的来临,直接促进了搭载智能操作系统、具有强大扩展性的智能手机、平板电脑等移动终端产业的蓬勃发展。来自美国最大的风险投资机构KPCB的数据显示,全球智能手机出货量正在以远高于台式电脑、笔记本电脑出货量的速度快速增长,该机构预计2011年全球智能手机出货量将达到4.13亿,超过台式电脑与笔记本电脑出货量的总和。 (2)智能手机的用户使用数量正在高速增长。据市场调研机构Gartner信息,2011年全球智能手机的总出货量将会达到4.68亿部,相比2010年实现了57.7%的增长,而谷歌Android操作系统将会在今年之内成为全球最大的智能手机操作系统。另外,全球市场调研机构IDC预计未来5年中国手机市场上,智能手机替代传统功能手机的趋势将日益明显,未来5年中国智能手机市场复合增长率将达到34.1%,人们对IT设备智能化的向往是这一增长率能够实现的主要因素,并且与其他国家相比,中国智能手机市场的发展空间更加广阔。 (3)操作系统格局预测:Android有望成为智能手机市场主导力量 搭载Android操作系统的智能手机目前已经成为市场上最炙手可热的智能产品。来自美国市场研究机构Gartner的数据显示,Android操作系统所占的市场份额从2008年的0.5%急剧增长到2011年的15.94%。开放的源代码和零成本已经让Android在全世界范围内受到青睐并迅速获得了主要手机厂商和数百万软件开发者的支持,Gartner预计,未来Android系统的市场份额有望超过其他操作系统,从而成为全球第一大智能手机操作系统。 2.安卓手机介绍 安卓手机指的是用Android操作系统的手机。安卓(Android)是基于Linux内核的操作系统,是Google公司在2007年11月5日公布的手机操作系统。 同样都是手机上面用的智能系统,安卓的系统是新生系统,界面更为华丽,开源性更强,当然因为是新生系统,所以在第三方软件方面暂时还不太多。因此,安卓应用程序的需求还是很迫切的。 3.软件人才需求 据业内统计,目前国内的Android研发人才缺口至少30万。由于目前Android技术较新,无论是相关书籍、培训还是大学教育,都处于初级阶段,因此Android人才短期将供不应求。从长期来看,随着各种移动应用和手机游戏等内容需求日益增加,也将激励大中小型手机应用开发商加大对Android应用的开发力度,因此Android人才的就业前景也非常广泛。 综上所述,在这样的背景下,安卓有很强的生命力。同时,作为一个新生的系统,其应用程序目前并不多,安卓应用程序的需求还是很迫切的,安卓研发人才的缺口还很大。这些都促进了我们学习开发安卓应用程序。 1.2开发环境 安卓应用程序开发环境如下: ①jdk1.8 ②android studio 4.0 ③Android SDK 二 安卓应用程序开发理论与方法 ButterKnife ButterKnife 是一个专注于 Android 系统的 View 注入框架,以前总是要写很多 findViewById 来找到 View 对象,有了 ButterKnife 可以很轻松地省去这些步骤。使用 ButterKnife 对性能基本没有损失,因为 ButterKnife 用到的注解并不是在运行时反射的,而是在编译的时候生成新的 class。项目集成起来特别方便,使用起来也特别简单。 ButterKnife 的优势: 强大的 View 绑定和 Click 事件处理功能,简化代码,提升开发效率 方便地处理 Adapter 里的 ViewHolder 绑定问题 运行时不会影响 APP 效率,使用配置方便 代码清晰,可读性强 SharedPreferences SharedPreferences 是使用键值对的方式来存储数据的。当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。而且 SharedPreferences 还支持多种不同的数据类型存储。 SQLite + OrmLite SQLite 是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百 KB 的内存就足够了,因而特别适合在移动设备上使用。SQLite 不仅支持标准的 SQL 语法,还遵循了数据库的 ACID 事务,所以只要以前是用过其他的关系型数据库,就可以很快地上手 SQLite。 ORM(全称 Object Relation Mapping)叫做对象关系映射,是一种程序设计技术,用于实现面向对象编程语言中不同类型系统的数据之间的转换。它可以直接将 Bean 文件转换成数据库中的表,Bean 中的属性就是表的列,它将繁琐的数据库操作封装成一个 Dao 类,使用 Dao 类和 Bean 可以直接对数据库进行操作,大多数的方法参数只有一个 Bean 对象。 多线程编程 Handler + Message Handler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用 Handler 的 sendMessage()方法,而发出的消息经过一系列的辗转处理后,最终会传递到 Handler 的 handleMessage()方法中。 Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。除了 what 字段,Message 还可以使用 arg1 和 arg2 字段来携带一些整型数据,使用 obj 字段携带一个 Object 对象。 Glide Glide 是一款快速高效的开源 Android 媒体管理和图片加载框架,它将媒体解码、内存和磁盘缓存以及资源池打包成一个简单易用的界面。 Glide 支持抓取、解码和显示视频图片、图像和动态 gif。Glide 包括一个灵活的 API,允许开发人员插入几乎任何网络堆栈。默认情况下,Glide 使用了一个定制的基于 HttpUrlConnection 的堆栈,但也包含了可插入谷歌的 Volley 项目或 Square 的 OkHttp 库的实用程序库。 Glide 的主要功能是尽可能平滑快速地滚动任何类型的图像列表,但它也适用于几乎任何需要获取、调整大小和显示远程图像的情况。 RecyclerView 控件 RecyclerView 是一个增强版的 ListView,不仅可以轻松实现和 ListView 同样的效果,还优化了 ListView 中存在的各种不足之处。同时 RecyclerView 支持横向滚动和瀑布流布局 Fragment + ViewPager Fragment 是一种可以嵌入在 Activity 当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用得非常广泛。它和 Activity 同样都能包含布局,同样都有自己的生命周期。甚至可以理解成一个迷你的 Activity。 ViewPager 是 android 扩展包 v4 包中的类,这个类可以让用户左右切换当前的 view。ViewPager 类直接继承了 ViewGroup 类,因此它一个容器类,可以添加其他的 View 类 ViewPager 类需要一个 PagerAdapter 适配器类给它提供数据(类似 RecyclerView)。 ViewPager 经常和 Fragment 一起使用,并且官方还提供了专门的 FragmentPagerAdapter 类供 ViewPager 使用。 三 记事本应用程序的设计与实现 3.1 拟解决的问题及目标 一个简单的记事本应用,在人们繁忙的时候更快速的记笔记,程序要实现的目标有如下几个: 登录注册 笔记顶置 开始游戏笔记增删查改 3.2 总体设计 1、记事本操作流程 先注册一个账号,登录进去,可以添加笔记,编辑笔记,顶置笔记,查找笔记 3.3 详细设计与编码实现 记事本界面 注册界面 新建笔记界面 编辑界面 个人信息界面 核心代码如下: RegisterActivity类 public class RegisterActivity extends AppCompatActivity { @BindView(R.id.btn_register) Button btnRegister; @BindView(R.id.btn_reset) Button btnReset; @BindView(R.id.check_hide_pwd_reg) CheckBox checkHidePwdReg; @BindView(R.id.check_hide_pwd_reg2) CheckBox checkHidePwdReg2; @BindView(R.id.edit_username_reg) EditText editUsernameReg; @BindView(R.id.edit_confirm_pwd_reg) EditText editConfirmPwdReg; @BindView(R.id.edit_email_reg) EditText editEmailReg; @BindView(R.id.edit_password_reg) EditText editPasswordReg; SharedPreferenceUtil spu; private static final String TAG = "RegisterActivity"; private UserDao userDao; private String textUserName; private String textPassword; private String textConfirmPwd; private String textEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_register); ButterKnife.bind(this); userDao = new UserDao(this); spu = SharedPreferenceUtil.getInstance(this); } @OnClick({R.id.btn_register, R.id.btn_reset, R.id.check_hide_pwd_reg, R.id.check_hide_pwd_reg2}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_register: // 检验非空 if (isNotEmpty()) { // 获得用户输入 getEditText(); // 检验密码 if (comparePwd()) { // 检查邮箱格式 if (checkEmail()) { // 检查邮箱是否可用 if (checkOnlyEmail()) { insertUserIntoDB(); queryAll(); Intent intent = new Intent(RegisterActivity.this, MainActivity.class); intent.putExtra(Constant.HAS_REGISTERED, true); startActivity(intent); finish(); } else { Toast.makeText(this, "邮箱已经被使用", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "用户名或密码不能为空", Toast.LENGTH_SHORT).show(); } break; case R.id.btn_reset: editUsernameReg.setText(""); editPasswordReg.setText(""); editConfirmPwdReg.setText(""); editEmailReg.setText(""); break; case R.id.check_hide_pwd_reg: if (checkHidePwdReg.isChecked()) { // 将密码显示出来 editPasswordReg.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editPasswordReg.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editPasswordReg.setSelection(editPasswordReg.getText().toString().length()); break; case R.id.check_hide_pwd_reg2: if (checkHidePwdReg2.isChecked()) { // 将密码显示出来 editConfirmPwdReg.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editConfirmPwdReg.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editConfirmPwdReg.setSelection(editConfirmPwdReg.getText().toString().length()); break; default: break; } } /** * 检验输入非空 * * @return */ public boolean isNotEmpty() { return !"".equals(editUsernameReg.getText().toString()) && !"".equals(editPasswordReg.getText().toString()) && !"".equals(editConfirmPwdReg.getText().toString()); } /** * 从控件中得到输入值 */ public void getEditText() { textUserName = editUsernameReg.getText().toString(); textPassword = editPasswordReg.getText().toString(); textConfirmPwd = editConfirmPwdReg.getText().toString(); textEmail = editEmailReg.getText().toString(); } /** * 检查邮箱是否可用 * * @return */ public boolean checkOnlyEmail() { List userBeans = userDao.queryForWhat("email", textEmail); return userBeans.size() == 0; } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 向数据库表插入数据 */ public void insertUserIntoDB() { UserBean userBean = new UserBean(textUserName, textPassword, textEmail); userDao.insert(userBean); // 同时存到SP中 spu.putString(Constant.USER_NAME, textUserName); spu.putString(Constant.PASSWORD, textPassword); } /** * 查询表中所有数据 */ public void queryAll() { List userBeans = userDao.queryAll(); for (int i = 0; i < userBeans.size(); i++) { Log.d(TAG, "queryAll: " + userBeans.get(i).toString()); } } } HomeActivity类 public class HomeActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener { @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.btn_top) RadioButton btnTop; @BindView(R.id.btn_add) RadioButton btnAdd; @BindView(R.id.btn_all) RadioButton btnAll; @BindView(R.id.dock_radio_group) RadioGroup dockRadioGroup; @BindView(R.id.drawer_layout) DrawerLayout drawerLayout; @BindView(R.id.nav_view) NavigationView navView; private static final String TAG = "HomeActivity"; ActionBar actionBar; Fragment fragment; FragmentManager manager = getSupportFragmentManager(); FragmentTransaction transaction = manager.beginTransaction(); SharedPreferenceUtil spu; private UserDao userDao; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); ButterKnife.bind(this); userDao = new UserDao(this); spu = SharedPreferenceUtil.getInstance(this); initView(); } /** * 初始化控件 */ public void initView() { // 工具栏 toolbar.setTitle(R.string.app_name); setTitleCenter(toolbar); setSupportActionBar(toolbar); actionBar = getSupportActionBar(); if (actionBar != null) { actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeAsUpIndicator(R.drawable.icon_setting); } // 抽屉 ViewGroup.LayoutParams params = navView.getLayoutParams(); params.width = getResources().getDisplayMetrics().widthPixels / 2; navView.setLayoutParams(params); navView.setNavigationItemSelectedListener(this); // 抽屉中的header View headerView = navView.getHeaderView(0); TextView textUserName = headerView.findViewById(R.id.header_user_name); TextView textEmail = headerView.findViewById(R.id.header_email); textUserName.setText(spu.getString(Constant.USER_NAME)); textEmail.setText(getEmail()); // 默认加载置顶Fragment fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); } /** * 单选按钮监听器 用来切换Fragment * * @param view * @param isChanged */ @OnCheckedChanged({R.id.btn_add, R.id.btn_all, R.id.btn_top}) public void onCheckedChanged(CompoundButton view, boolean isChanged) { transaction = manager.beginTransaction(); switch (view.getId()) { case R.id.btn_top: if (isChanged) { fragment = new TopFragment(); transaction.replace(R.id.view_pager, fragment, Constant.TOP_TAG); transaction.commit(); Constant.PAGE_STATE = "top"; } break; case R.id.btn_add: if (isChanged) { fragment = new AddFragment(); transaction.replace(R.id.view_pager, fragment, Constant.ADD_TAG); transaction.commit(); } break; case R.id.btn_all: if (isChanged) { fragment = new AllFragment(); transaction.replace(R.id.view_pager, fragment, Constant.LIST_TAG); transaction.commit(); Constant.PAGE_STATE = "all"; } break; default: break; } } /** * 获得登录用户的邮箱 * * @return */ public String getEmail() { List userBeans = userDao .queryByUserNameAndPassword(spu.getString(Constant.USER_NAME), spu.getString(Constant.PASSWORD)); return userBeans.get(0).getEmail(); } /** * 抽屉中菜单的点击事件 * * @param item * @return */ @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { drawerLayout.closeDrawers(); switch (item.getItemId()) { case R.id.nav_change_pwd: DialogUtil.editInfoDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_dismiss: DialogUtil.dismissDialog(this, spu.getInt(Constant.USER_ID)); break; case R.id.nav_exit: spu.putBoolean(Constant.AUTO_LOGIN, false); Intent intent = new Intent(HomeActivity.this, MainActivity.class); startActivity(intent); finish(); break; default: break; } return true; } /** * ToolBar的menu * * @param menu * @return */ @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.toolbar_menu, menu); setIconsVisible(menu, true); return true; } /** * 重写ToolBar上菜单点击事件 * 按照条件查找 * * @param item * @return */ @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()) { case R.id.search_title: DialogUtil.searchTitleDialog(this); break; case R.id.search_content: DialogUtil.searchContentDialog(this); break; case R.id.search_category: DialogUtil.searchCategoryDialog(this); break; case android.R.id.home: drawerLayout.openDrawer(GravityCompat.START); break; default: break; } return true; } /** * ToolBar标题居中 * * @param toolbar */ public void setTitleCenter(Toolbar toolbar) { String title = "title"; final CharSequence originalTitle = toolbar.getTitle(); toolbar.setTitle(title); for (int i = 0; i < toolbar.getChildCount(); i++) { View view = toolbar.getChildAt(i); if (view instanceof TextView) { TextView textView = (TextView) view; if (title.equals(textView.getText())) { textView.setGravity(Gravity.CENTER); Toolbar.LayoutParams params = new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.MATCH_PARENT); params.gravity = Gravity.CENTER; textView.setLayoutParams(params); } } toolbar.setTitle(originalTitle); } } /** * menu显示图标 * * @param menu * @param flag */ private void setIconsVisible(Menu menu, boolean flag) { // 判断menu是否为空 if (menu != null) { try { // 如果不为空,就反射拿到menu的setOptionalIconsVisible方法 Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE); // 暴力访问该方法 method.setAccessible(true); // 调用该方法显示icon method.invoke(menu, flag); } catch (Exception e) { e.printStackTrace(); } } } FindPwdActivity类 public class FindPwdActivity extends AppCompatActivity { @BindView(R.id.btn_confirm_find) Button btnConfirmFind; @BindView(R.id.btn_reset_find) Button btnResetFind; @BindView(R.id.edit_confirm_pwd_find) EditText editConfirmPwdFind; @BindView(R.id.edit_password_find) EditText editPasswordFind; @BindView(R.id.edit_email_find) EditText editEmailFind; @BindView(R.id.check_hide_pwd_find) CheckBox checkHidePwdFind; @BindView(R.id.check_hide_pwd_find2) CheckBox checkHidePwdFind2; private static final String TAG = "FindPwdActivity"; private UserDao userDao; private String textPassword; private String textConfirmPwd; private String textEmail; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_find_pwd); ButterKnife.bind(this); userDao = new UserDao(this); } @OnClick({R.id.btn_confirm_find, R.id.btn_reset_find, R.id.check_hide_pwd_find, R.id.check_hide_pwd_find2}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_confirm_find: // 检查非空 if (isNotEmpty()) { // 获得用户输入 getEditText(); // 检查邮箱格式 if (checkEmail()) { // 检查两次输入的密码是否一致 if (comparePwd()) { // 更新密码 if (updatePwdFromDB()) { // 跳转登录界面 Intent intent = new Intent(FindPwdActivity.this, MainActivity.class); startActivity(intent); FindPwdActivity.this.finish(); } } else { Toast.makeText(this, "两次输入的密码不一致", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱格式错误", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "邮箱或密码不能为空", Toast.LENGTH_SHORT).show(); } break; case R.id.btn_reset_find: // 清空输入 editPasswordFind.setText(""); editConfirmPwdFind.setText(""); editEmailFind.setText(""); break; case R.id.check_hide_pwd_find: if (checkHidePwdFind.isChecked()) { // 将密码显示出来 editPasswordFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editPasswordFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editPasswordFind.setSelection(editPasswordFind.getText().toString().length()); break; case R.id.check_hide_pwd_find2: if (checkHidePwdFind2.isChecked()) { // 将密码显示出来 editConfirmPwdFind.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); } else { // 隐藏密码 editConfirmPwdFind.setTransformationMethod(PasswordTransformationMethod.getInstance()); } // 将光标移动到文本最后 editConfirmPwdFind.setSelection(editConfirmPwdFind.getText().toString().length()); break; default: break; } } /** * 检验输入非空 * * @return */ public boolean isNotEmpty() { return !"".equals(editPasswordFind.getText().toString()) && !"".equals(editConfirmPwdFind.getText().toString()) && !"".equals(editEmailFind.getText().toString()); } /** * 从控件中得到输入值 */ public void getEditText() { textPassword = editPasswordFind.getText().toString(); textConfirmPwd = editConfirmPwdFind.getText().toString(); textEmail = editEmailFind.getText().toString(); Log.d(TAG, "getEditText: " + textEmail); } /** * 检查邮箱格式 * * @return */ public boolean checkEmail() { Matcher emailMatcher = Constant.EMAIL_PATTERN.matcher(textEmail); return emailMatcher.matches(); } /** * 验证两次输入的密码是否一致 * * @return */ public boolean comparePwd() { return textPassword.equals(textConfirmPwd); } /** * 修改数据库中的密码 * * @return 邮箱是否存在 */ public boolean updatePwdFromDB() { List userBeans = userDao.queryForWhat("email", textEmail); if (userBeans.size() != 0) { UserBean user = userBeans.get(0); user.setPassword(textPassword); userDao.update(user); return true; } else { Toast.makeText(this, "邮箱错误", Toast.LENGTH_SHORT).show(); return false; } } } } public void onLeaveApplication(Ad arg0) { // TODO Auto-generated method stub } public void onFailedToReceiveAd(Ad arg0, ErrorCode arg1) { // TODO Auto-generated method stub } public void onDismissScreen(Ad arg0) { // TODO Auto-generated method stub } }); View gameMessage = findViewById(R.id.GameMessage); int[] data = getSettingData(); TextView levelMessage = (TextView)findViewById(R.id.level_Message); levelMessage.setText("SCORE: "+data[0]+"\nBEST: "+data[1]); gameMessage.setOnClickListener(new View.OnClickListener() { public void onClick(View arg0) { Intent intent = new Intent(LoadingActivity.this, GameBirdActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); finish(); } }); } private int[] getSettingData() { SharedPreferences gb_settings = getSharedPreferences(GameBirdActivity.GameBirdSettingsFile, 0); int last = gb_settings.getInt(GameBirdActivity.Settings_LevelLast, 0); int top = gb_settings.getInt(GameBirdActivity.Settings_LevelTop, 0); return new int[]{last, top}; } public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { try{ GameBirdActivity.instance.finish(); }catch(Exception e){} finish(); System.exit(0); return true; } return super.onKeyDown(keyCode, event); } } 四 总结 100[/caption]