安卓APP源码和设计报告——麻雀笔记

news2024/11/17 7:43:15

目录

一 安卓应用程序开发背景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

二 安卓应用程序开发理论与方法

  1. ButterKnife
    ButterKnife 是一个专注于 Android 系统的 View 注入框架,以前总是要写很多 findViewById 来找到 View 对象,有了 ButterKnife 可以很轻松地省去这些步骤。使用 ButterKnife 对性能基本没有损失,因为 ButterKnife 用到的注解并不是在运行时反射的,而是在编译的时候生成新的 class。项目集成起来特别方便,使用起来也特别简单。
    ButterKnife 的优势:
    强大的 View 绑定和 Click 事件处理功能,简化代码,提升开发效率
    方便地处理 Adapter 里的 ViewHolder 绑定问题
    运行时不会影响 APP 效率,使用配置方便
    代码清晰,可读性强
  2. SharedPreferences
    SharedPreferences 是使用键值对的方式来存储数据的。当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这个键把相应的值取出来。而且 SharedPreferences 还支持多种不同的数据类型存储。
  3. SQLite + OrmLite
    SQLite 是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百 KB 的内存就足够了,因而特别适合在移动设备上使用。SQLite 不仅支持标准的 SQL 语法,还遵循了数据库的 ACID 事务,所以只要以前是用过其他的关系型数据库,就可以很快地上手 SQLite。
    ORM(全称 Object Relation Mapping)叫做对象关系映射,是一种程序设计技术,用于实现面向对象编程语言中不同类型系统的数据之间的转换。它可以直接将 Bean 文件转换成数据库中的表,Bean 中的属性就是表的列,它将繁琐的数据库操作封装成一个 Dao 类,使用 Dao 类和 Bean 可以直接对数据库进行操作,大多数的方法参数只有一个 Bean 对象。
  4. 多线程编程 Handler + Message
    Handler 顾名思义也就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用 Handler 的 sendMessage()方法,而发出的消息经过一系列的辗转处理后,最终会传递到 Handler 的 handleMessage()方法中。
    Message 是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。除了 what 字段,Message 还可以使用 arg1 和 arg2 字段来携带一些整型数据,使用 obj 字段携带一个 Object 对象。
  5. Glide
    Glide 是一款快速高效的开源 Android 媒体管理和图片加载框架,它将媒体解码、内存和磁盘缓存以及资源池打包成一个简单易用的界面。
    Glide 支持抓取、解码和显示视频图片、图像和动态 gif。Glide 包括一个灵活的 API,允许开发人员插入几乎任何网络堆栈。默认情况下,Glide 使用了一个定制的基于 HttpUrlConnection 的堆栈,但也包含了可插入谷歌的 Volley 项目或 Square 的 OkHttp 库的实用程序库。
    Glide 的主要功能是尽可能平滑快速地滚动任何类型的图像列表,但它也适用于几乎任何需要获取、调整大小和显示远程图像的情况。
  6. RecyclerView 控件
    RecyclerView 是一个增强版的 ListView,不仅可以轻松实现和 ListView 同样的效果,还优化了 ListView 中存在的各种不足之处。同时 RecyclerView 支持横向滚动和瀑布流布局
  7. Fragment + ViewPager

Fragment 是一种可以嵌入在 Activity 当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用得非常广泛。它和 Activity 同样都能包含布局,同样都有自己的生命周期。甚至可以理解成一个迷你的 Activity。

ViewPager 是 android 扩展包 v4 包中的类,这个类可以让用户左右切换当前的 view。ViewPager 类直接继承了 ViewGroup 类,因此它一个容器类,可以添加其他的 View 类 ViewPager 类需要一个 PagerAdapter 适配器类给它提供数据(类似 RecyclerView)。

ViewPager 经常和 Fragment 一起使用,并且官方还提供了专门的 FragmentPagerAdapter 类供 ViewPager 使用。

三 记事本应用程序的设计与实现

3.1 拟解决的问题及目标

一个简单的记事本应用,在人们繁忙的时候更快速的记笔记,程序要实现的目标有如下几个:

  1. 登录注册
  2. 笔记顶置
  3. 开始游戏笔记增删查改

3.2 总体设计

1、记事本操作流程

先注册一个账号,登录进去,可以添加笔记,编辑笔记,顶置笔记,查找笔记

3.3 详细设计与编码实现

  1. 记事本界面


注册界面


新建笔记界面


编辑界面


个人信息界面

  1. 核心代码如下:

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<UserBean> 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<UserBean> 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<UserBean> 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<UserBean> 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/70681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

四年一次的世界杯来了,看看还剩下哪些赛程呢?

足球世界杯的由来2022年的世界杯目前世界杯的赛程看看排在前十的球员几个疑问&#xff1f;世界杯的由来 足球大家应该知道&#xff0c;是一项体育运动&#xff0c;而且是一项多人的体育运动。 世界杯的诞生&#xff0c;源于1950年的南非公开赛&#xff0c;在当时只有5支队伍参…

微信视频播放点播小程序毕业设计,在线教育视频学习小程序系统设计与实现,微信小程序毕业设计论文怎么写毕设源码开题报告需求分析怎么做

基于微信小程序的毕业设计题目&#xff08;12&#xff09;php在线教育视频点播学习小程序(含开题报告、任务书、中期报告、答辩PPT、论文模板) 项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于微信小程序视频点播系统&#xff0c;前台用户使用小程序&a…

理解Nodejs中的进程间通信

前置知识 文件描述符 在 Linux 系统中&#xff0c;一切都看成文件&#xff0c;当进程打开现有文件时&#xff0c;会返回一个文件描述符。 文件描述符是操作系统为了管理已经被进程打开的文件所创建的索引&#xff0c;用来指向被打开的文件。 当我们的进程启动之后&#xff0c…

Python学习-8.1.2 标准库(random库的基础与实例)

2.2 random库 使用random库的主要目的是生成随机数 2.2.1 产生随机数 random()函数&#xff1a;生成一个[0.0,1.0)之间的随机小数&#xff0c;左开右闭。 import random print(random.random())#生成一个[0.0,1.0)之间的随机小数 #每次运行random()函数都会产生不同的数据 …

Layer2代币经济学:除了治理 还应该具备什么价值?

为什么我们需要L2&#xff1f; 任何在2021年期间使用以太坊的人都知道&#xff0c;该区块链可能会变得非常拥堵。这是一个典型的问题——需求太多而供应不足。因此&#xff0c;gas费用&#xff08;交易费&#xff09;变得相当昂贵。在牛市高峰期&#xff0c;使用以太坊区块链发…

基于Jenkins的开发测试全流程持续集成实践

今年一直在公司实践CI&#xff0c;本文将近半年来的一些实践总结一下&#xff0c;可能不太完善或优美&#xff0c;但的确初步解决了我目前所在项目组的一些痛点。当然这仅是一家之言也不够完整&#xff0c;后续还会深入实践和引入Kubernetes进行容器编排&#xff0c;以及通过阿…

从js中加载图片和Cannot read property ‘appendChild‘ of null 错误

先写一段代码如下&#xff1b; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title> </title><script>var imgnew Image();img.addEventListener("load",loadHandler);img.src"img/1.jpg"…

【JMeter】命令参数说明

jmeter -n -t xxx.jmx -l result.jtl 非GUI运行xxx.jml脚本写入xxx.jtl结果文件 jmeter -n -t xxx.jmx -l result.jtl -j run.log 非GUI运行xxx.jmx脚本写入xxx.jtl结果文件&#xff0c;日志记录到run.log jmeter -n -t xxx.jmx -R ip1:port1,ip2:port2 -l result.jtl 使用远…

详解 Redis 持久化之掌握 RDB ⽂件的格式,学习如何制作数据库镜像

本文带大家了解一下 Redis 数据一种持久化方式 RDB 的实现。包括 Redis 内存快照 RDB ⽂件的创建时机以及⽣成⽅法。可以让你掌握 RDB ⽂件的格式&#xff0c;学习如何制作数据库镜像。 RDB 创建的入口函数 Redis 创建 RDB 文件的函数有三个&#xff0c;分别是 rdbSave, rdbSa…

知识图谱-KGE-语义匹配-双线性模型-2017:ANALOGY

【paper】 Analogical Inference for Multi-relational Embeddings【简介】 本文是卡耐基梅隆大学的中国学者发表在 ICML 2017 上的工作&#xff0c;提出了 ANALOGY 模型&#xff0c;用于建模实体和关系的推理属性。这个模型应当也算是双线性模型中比较经典的一个了&#xff0c…

Erueka基本使用

SpringCloud Erueka基本使用 Erueka是微服务架构中&#xff0c;可以作为注册中心的技术实现&#xff0c;如下图所示 服务提供者&#xff1a;一次业务中&#xff0c;暴露接口给其它微服务调用&#xff0c;被其它微服务调用的服务。&#xff08;提供接口给其它微服务&#xff09…

一个超好看的音乐网站设计与实现(HTML+CSS)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

vue+vite的创建

1、创建vue3项目 yarn create vite效果&#xff1a; yarn create v1.22.19 [1/4] Resolving packages... [2/4] Fetching packages... [3/4] Linking dependencies... [4/4] Building fresh packages...success Installed "create-vite3.2.1" with binaries:- crea…

接口管理测试繁琐复杂?何不试试这个神器

一、前言 作为一名测试从业者&#xff0c;深刻的明白接口测试在项目过程中是多么重要的一个环节。通过页面进行的UI测试会因为界面不稳定而导致用例维护非常困难。另外&#xff0c;在检查系统的安全性、稳定性上面也是尤为重要的环节&#xff0c;这些也是无法通过前端测试的&a…

Redis - Windows下载与安装

1.获取Redis在windows下的安装包 Windows版下载地址&#xff1a;https://github.com/microsoftarchive/redis/releases 选择Redis-x64-*.zip 2.解压zip文件与配置 2.1 选取目录 选取一个目录作为解压目录&#xff0c;这个目录就是你Redis程序所在位置&#xff0c;尽量找一…

【软件测试】师傅给我的测试新手“真理“宝典......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 熟悉你所测试的软件…

java学习day59(乐友商城)Vue入门

0.前言 前几天我们已经对后端的技术栈有了初步的了解、并且已经搭建了整个后端微服务的平台。接下来要做的事情就是功能开发了。但是没有前端页面&#xff0c;我们肯定无从下手&#xff0c;因此今天我们就要来了解一下前端的一些技术&#xff0c;完成前端页面搭建。 先聊一下…

【Redis】Redis实现分布式锁解析与应用(Redis专栏启动)

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;专注于研究 Java/ Liunx内核/ C及汇编/计算机底层原理/源码&#xff0c;就职于大型金融公司后端高级工程师&#xff0c;擅长交易领域的高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 &#x1…

java版商城+Spring Cloud+SpringBoot+mybatis+uniapp b2b2c o2o 多商家入驻商城 直播带货商城 电子商务

一个好的SpringCloudSpringBoot b2b2c 电子商务平台涉及哪些技术、运营方案&#xff1f;以下是我结合公司的产品做的总结&#xff0c;希望可以帮助到大家&#xff01; 搜索体验小程序&#xff1a;海哇 1. 涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买…

助农销售平台毕业设计,农产品销售管理系统设计与实现,毕业设计怎么写论文源码开题报告需求分析怎么做

项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于web网页的多用户商城系统&#xff0c;整个网站项目使用了B/S架构&#xff0c;基于java的springboot框架下开发&#xff1b;用户通过登录网站&#xff0c;查询商品&#xff0c;购买商品&#xff0c;下单&…