期末安卓大作业——熊猫记事本 熊猫日记ol下载安装
yuyutoo 2024-10-30 06:32 6 浏览 0 评论
一、应用程序功能
基本功能:
- 基于 Android 平台实现简单的个人笔记管理的 APP
2. 要求提供登录界面给用户
3. 要求有界面让用户输入笔记内容(包括但不限于以下类型内容:笔记标题, 记录时间,记录地点,内容(可以是文字,支持图片,声音等更好))
4. 笔记可以分类管理(类别可以自定义)
5. 支持按照时间、按照内容进行查询。登陆后首页展示列表,点击列表上的某 一项支持查看笔记明细等
6. 以上内容要求记入 SQLITE 或者文件系统中,APP 重启后不丢失。
拓展功能:
1 、修改登录密码(界面隐蔽,不易被找到)
2 、覆盖自定义了导航栏
3 、支持按照关键字,模糊搜索笔记
4 、支持按照开始结束时间,范围搜索笔记
5 、通过加锁实现私密笔记和普通笔记的分类
6 、可以设置笔记提醒时间,即闹铃
7 、设置了分享按钮
二、程序功能设计
图 2.1 系统功能结构
三、实现原理
(1)登录密码判断
通过一个延时动画,从 Main2Activity 跳转到登录界面(LoginActivity), 在登录界面定义一个 fileIsExists 方法来判断是否设置过密码,方法里通过
File f=new File(getFilesDir ()+"/abc.txt")来读取私有目录下的文件。点击 登录按钮时,调用此方法判断,若文件中不存在已有密码,则设定初始密码为 “0000 ”并写入文件;若文件中已有密码,则与 EditText 中输入的密码进行比 较,相等则跳转到主界面(MainActivity)。若输入密码错误,会进行友好 Toast 提示,显示"密码错误!!!002"+正确密码,这样知道规则的记事本使用者就会 想起所设定的密码。
图 3-1-1 延时动画与简介页面
图 3-1-2 登录界面
(2)对修改记事和新增记事的判断
由于在主界面中,单击已有记事显示明细和新增记事的方法最后都会跳转到 AddActivity ,这时候需要体现出界面的不同来。我是通过 putExtra 方法将键值对 放入 intent 中,定义 update 和 newadd 两个不同的 value,然后跳转时候将 intent 传过去在 AddActivity 中进行判断。在它的 onCreate 方法中调动一个自定义的加 载数据函数 loadData ,来实现对传过来的健进行判断。
部分核心代码如下:
表 3-2 AddActivity.java
/加载数据private void loadData() {/如果是新增记事模式,则将editText清空if (editModel.equals("newAdd")) {et_Notes.setText("");}/如果编辑的是已存在的记事,则将数据库的保存的数据取出,并显示在 EditText中else if (editModel.equals("update")) {tv_title.setText("编辑记事");dop.create_db(); |
Cursor cursor = dop.query_db(item_Id);cursor.moveToFirst();/取出数据库中相应的字段内容context = cursor.getString (cursor.getColumnIndex("context")); datatype =cursor.getString (cursor.getColumnIndex("datatype"));datatime =cursor.getString (cursor.getColumnIndex("datatime"));locktype =cursor.getString (cursor.getColumnIndex("locktype"));lock = cursor.getString (cursor.getColumnIndex("lock")); |
图 3-2 判断新增记事和编辑记事
(3)模糊搜索实现
先通过搜索框的 getText 获得输入的关键字,再用 if 判断输入的是否为空, 若不为空 ,则通过键值对的形式把关键字放入 intent 中进行跳转 ,跳转到 SearchActivity 。在 SearchActivity 中定义一个 showNotesList 的方法,通过调用数 据库操作类 DatabaseOperation 中定义的 query_db(keword)方法进行模糊查询, 最后通过实例化自定义的适配器方法将搜索到的笔记信息动态装载到首页。
部分核心代码如下:
表 3-3 SearchActivity.java
// 显示记事列表private void showNotesList() {/打开数据库dop.create_db();Cursor cursor = dop.query_db(keword);/%模糊查询if (cursor.getCount() > 0) {List<SQLBean> list = new ArrayList<SQLBean>();/实例化数据列表while (cursor.moveToNext()) {/光标移动成功SQLBean bean = new SQLBean ();/创建数据库实体类 /保存日记信息id到实体类bean.set_id("" +cursor.getInt(cursor.getColumnIndex("_id")));/保存日记内容到实体类bean.setContext(cursor.getString (cursor.getColumnIndex("context")));/保存日记标题到实体类bean.setTitle(cursor.getString (cursor.getColumnIndex("title")));/保存日记记录时间到实体类bean.setTime(cursor.getString (cursor.getColumnIndex("time")));/保存日记是否设置提醒时间到实体类bean.setDatatype(cursor.getString (cursor.getColumnIndex("datatype")));/保存日记提醒时间到实体类bean.setDatatime(cursor.getString (cursor.getColumnIndex("datatime")));/保存日记是否设置了日记锁到实体类bean.setLocktype(cursor.getString (cursor.getColumnIndex("locktype")));/保存日记锁秘密到实体类bean.setLock(cursor.getString (cursor.getColumnIndex("lock")));/把保存日记信息实体类保存到日记信息集合里list.add(bean);} |
/倒序显示数据Collections.reverse(list);/装载日记信息到首页MainAdapter adapter = new MainAdapter (list, this);/日记列表设置日记信息适配器lv_notes.setAdapter (adapter);}else{Toast.makeText(SearchActivity.this, "暂无记事!",Toast.LENGTH LONG).show();}/关闭数据库dop.close_db();} |
图 3-3 模糊搜索
(4) 日期范围搜索实现
与模糊搜索类似,不过 SQL 判断的时候需要注意,要在月份前补 0,否则语句会 出错。然后也是带参数跳转到专门的一个处理类 DataSearchActivity,与前面 的模糊查询不同之处在于 ,这里调用的是另一个自定义的数据库操作类 query_db(startData, endData)
部分核心代码如下
表 3-4 MainActivity.java
// 日期范围搜索public void onData(View v) {// 最后一个 false 表示不显示日期,如果要显示日期,最后参数可以是 true 或者不用输入Calendar c = Calendar.getInstance();new DoubleDatePickerDialog (MainActivity.this, 0,new DoubleDatePickerDialog.OnDateSetListener () { @Overridepublic void onDateSet(DatePicker startDatePicker,in t startYear, in tstartMonthOfYear,in t startDayOfMonth, DatePickerendDatePicker,int endYear, int endMonthOfYear,int endDayOfMonth) {if (startYear < endYear || startYear == endYear && startMonthOfYear <= endMonthOfYear) {in t st = startMonthOfYear + 1;in t et = endMonthOfYear + 1;Intent intent = new Intent(MainActivity.this, DataSearchActivity.class);//跳转到日期搜索// sql 判断 需要在月份前补 0 否则 sql 语句判断 不正确。if (st < 10) {intent.putExtra("startData", startYear +"-0"+ st + "-" + "01");} else {intent.putExtra("startData", startYear +" "-+ st + "-" + "01");}if (et < 10) {intent.putExtra("endData", endYear + "-0" + et |
+ "-" + "30");} else {intent.putExtra("endData", endYear + "-" + et+ "-" + "30");}startActivity (intent);} else {Toast.makeText(MainActivity.this, " 日期选择错误请重新选择!",Toast.LENGTH_LONG).show(); }}}, c.get(Calendar.YEAR), c.get(Calendar.MONTH), c .get(Calendar.DATE), false).show();} |
(5)长按弹出框功能实现
在主界面(MainActivity)、模糊搜索展示界面(SearchActivity)和日期搜索展示 界面(DataSearchActivity)中都重写了 onStart 方法,里面加入了显示记事明细 方法、为单击记事和长按记事添加了监听器,然后在弹出的对话框中所选会被 switch 语句所匹配,再进行相应的操作。
部分核心代码如下:
表 3-5-1 onStart 方法的重写
@Overrideprotected void onStart() {/ TODO Auto-generated method stubsuper.onStart();/显示记事列表showNotesList();/为记事列表添加监听器lv_notes.setOnItemClickListener (new ItemClickEvent());/为记事列表添加长按事件lv_notes.setOnItemLongClickListener (new ItemLongClickEvent()); } |
表 3-5-2 单击与长按监听器
/记事列表单击监听器class ItemClickEvent implements OnItemClickListener {@Overridepublic void onItemClick(AdapterView<?> parent, View view, in t position,long id) {tv_note_id = (TextView) view.findViewById(R.id.tv noteid);tv_locktype = (TextView) view.findViewById(R.id.tv locktype); tv_lock = (TextView) view.findViewById(R.id.tv lock);String locktype = tv_locktype.getText().toString (); String lock = tv_lock.getText().toString ();in t item_id = Integer.parseInt(tv_note_id.getText().toString ()); if ("0".equals(locktype)) {/如果没加锁Intent intent = new Intent(MainActivity.this,AddActivity.class);intent.putExtra("editModel", "update");intent.putExtra("noteId", item_id);startActivity (intent);} else {inputTitleDialog (lock, 0, item_id); |
}}}/记事列表长按监听器class ItemLongClickEvent implements OnItemLongClickListener {@Overridepublic boolean onItemLongClick(AdapterView<?> parent, View view, in t position, long id) {/初始化日记id保存控件tv_note_id = (TextView) view.findViewById(R.id.tv noteid);/初始化是否添加日记锁保存控件tv_locktype = (TextView) view.findViewById(R.id.tv locktype);/初始化日记锁秘密保存信息tv_lock = (TextView) view.findViewById(R.id.tv lock);/获取控件上是否设置日记锁信息String locktype = tv_locktype.getText().toString ();/获取控件上日记密码信息String lock = tv_lock.getText().toString ();/获取控件上id信息转换成int类型in t item_id = Integer.parseInt(tv_note_id.getText().toString ());/弹出选择操作框方法simpleList(item_id, locktype, lock);return true;}} |
表 3-5-3 弹出对话框
/简单列表对话框,用于选择操作public void simpleList(final in t item_id, final String locktype, final String lock) {/实例化AlertDialogAlertDialog.Builder alertDialogBuilder = newAlertDialog.Builder (this,R.style.custom dialog);/设置弹窗标题alertDialogBuilder.setTitle("选择操作");/设置弹窗图片alertDialogBuilder.setIcon (R.mipmap.ic launcher);/设置弹窗选项内容alertDialogBuilder.setItems(R.array.itemOperation,new android.content.DialogInterface.OnClickListener () {@Overridepublic void onClick(DialogInterface dialog, in t which) { |
switch (which) {/编辑case 0:if ("0".equals(locktype)) {/判断是否添加了秘密锁0没有Intent intent = new Intent(MainActivity.this, AddActivity.class);/跳转到添加日记页intent.putExtra("editModel", "update");/传递编辑信息intent.putExtra("noteId", item_id);/传递id信息startActivity (intent);/开始跳转 } else {/有秘密锁/弹出输入密码框inputTitleDialog (lock, 0, item_id); }break;/删除case 1:if ("0".equals(locktype)) {/判断是否是加密日记0没有dop.create_db();/打开数据库dop.delete_db(item_id);/删除数据 dop.close_db();/关闭数据库/刷新列表显示lv_notes.invalidate();showNotesList();} else {/有秘密锁/弹出输入密码框inputTitleDialog (lock, 1, item_id);/刷新列表显示lv_notes.invalidate();/显示日记列表信息showNotesList();}break;}}});alertDialogBuilder.create();/创造弹窗alertDialogBuilder.show();/显示弹窗} |
图 3-5 长按实现弹出框
(6)闹钟提醒的实现
在 AddActivity 中定义字符串 datatype 代表是否设置了闹钟,字符串 datatime 代表提醒时间,并定义闹钟设置方法,并判断之前有没有设置过闹钟提醒。若没 有,则先通过 DataFormat 格式化当前时间,并显示,然后把保存是否设置闹钟 的变量 datatime 设置为 1。这样当编辑此次记事结束时候,点击右上角√按钮 时 候 , 调 用 自 定 义 数据 库操 作类 方 法 update_db(title, context, time, datatype, datatime,locktype, lock, item_Id)就可以保存状态到数据库中。
还有一点要注意,不然做出的闹钟会有问题,那就是在最初的主界面重写的 onCreate 方法中要考虑闹钟。即需要通过 AlarmManager 先获取系统服务,然后 跳转到 CallAlarm 判断是否已经到了闹钟提醒时间,若是则将参数 shake 和 ring 设置为 true,传参跳转到闹钟具体实现类 AlarmAlert 从而弹出闹钟,播放声音 并震动(虽然虚拟机不会震动哈哈)
部分核心代码:
表 3-6 MainActivity 中重写的 onCreate 方法
@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bt_add = (Button) findViewById(R.id.btad);bt_add.setOnClickListener (new ClickEvent());et_keyword = (EditText) findViewById(R.id.et keyword);/数据库操作dop = new DatabaseOperation (this, db);lv_notes = (MyGridView) findViewById(http://R.id.lv notes);if (am == null) {am = (AlarmManager) getSystemService(ALARM SERVICE);/通过系统服 务获取}try {Intent intent = new Intent(MainActivity.this,CallAlarm.class);/onCreate方法中先判断闹钟PendingIntent sender = PendingIntent.getBroadcast( MainActivity.this, 0, intent, 0);am.setRepeating (AlarmManager.RTC WAKEUP, 0, 60 * 1000, sender);} catch (Exception e) {e.printStackTrace();}} |
图 3-6- 1 设定闹钟及闹钟图标的显示
图 3-6-2 闹钟显示及闹钟图标的消失
(7)记事加密实现
与闹钟的定义类似,通过定义 locktype代表是否加密,lock 代表密码。在点击加 密锁的图标后,判断 locktype 的值,来判断是否已经设置了密码。若值为 0 则代 表未设置,调用自定义的 inputlockDialog 方法弹出密码设置窗口,然后把 locktype 设为 1 ,把锁的图标换成上锁的图案;若 locktype 为 1 ,即代表已设置过密码, 调用自定义的 inputunlockDialog 方法弹出是否取消密码的窗口,监听器判断若点 击的是确认,则将 locktype 和 lock 重置为 0 ,再将锁的图标换成未加锁的图片。 在自定义的适配器 MainAdapter 重写的 getView 函数中调用模型层的 getLocktype 获取判断是否上锁,若不上锁则正常显示。若上锁,则主界面不显示记事的 title, 并将记事的背景设为一个大大锁的图案。
核心代码分析:
表 3-7-1 设置密码弹窗
/设置密码弹窗private void inputlockDialog () {final EditText inputServer = new EditText(this);/创建EditText输 入框inputServer.setInputType(InputType.TYPE CLASS TEXT| InputType.TYPE TEXT VARIATION PASSWORD);/设置输入框类 型inputServer.setFocusable(true);/获取焦点AlertDialog.Builder builder = new AlertDialog.Builder (this);/创建 弹出框builder.setTitle("设置密码").setView(inputServer).setNegativeButton ("取消", null);/在弹窗上设置标题添加输入框builder.setPositiveButton ("确认", newDialogInterface.OnClickListener () {public void onClick(DialogInterface dialog, in t which) {/设置 确认按钮String inputName = inputServer.getText().toString ();if ("".equals(inputName)) {/判断输入框内容是否为空Toast.makeText(AddActivity.this, "密码不能为空 请重新输入!",Toast.LENGTH LONG).show();} else {/输入框内容不为空lock = inputName;/密码locktype = "1";/添加了密码锁ib_lk.setBackgroundResource(R.drawable.locky);/设置添加锁图案Toast.makeText(AddActivity.this, "密码设置成功!", Toast.LENGTH LONG).show();} |
}});builder.show();/弹出设置密码弹窗} |
表 3-7-2 getView 中的判断
@Overridepublic View getView(final in t position, View convertView, ViewGroup parent) {Holder holder;if (convertView == null) {holder = new Holder ();convertView = inflater.inflate(R.layout.note item, null); holder.tv_note_id = (TextView) convertView.findViewById(http://R.id.tv noteid);holder.tv_locktype= (TextView) convertView.findViewById(http://R.id.tv locktype);holder.tv_lock= (TextView) convertView.findViewById(http://R.id.tv lock);holder.tv_note_title = (TextView) convertView.findViewById(http://R.id.tv note title);holder.tv_note_time = (TextView) convertView.findViewById(http://R.id.tv note time);holder.iv_img e = (ImageView)convertView.findViewById(R.id.iv imge);holder.im_datatime = (ImageView) convertView.findViewById(http://R.id.im datatime);holder.ll_bg = (RelativeLayout) convertView.findViewById(R.id.ll bg);convertView.setTag (holder);} else {holder = (Holder) convertView.getTag ();}dm = context.getResources().getDisplayMetrics();/获得系统屏幕信息 LinearLayout.LayoutParams imagebtn_params = newLinearLayout.LayoutParams(WindowManager.LayoutParams.WRAP CONTENT,WindowManager.LayoutParams.WRAP CONTENT);imagebtn_params.width = dm.widthPixels / 2;/imagebtn_params.height = dm.widthPixels / 2;/holder.ll_bg.setLayoutParams(imagebtn_params);holder.tv_note_id.setText(list.get(position).get_id());holder.tv_note_title.setText(list.get(position).getTitle()); |
holder.tv_note_time.setText(list.get(position).getTime());holder.tv_locktype.setText(list.get(position).getLocktype()); holder.tv_lock.setText(list.get(position).getLock());if (list.get(position).getDatatype().equals("0")) {/判断是否开启提 醒功能holder.im_datatime.setVisibility (View.GONE);} else {holder.im_datatime.setVisibility (View.VISIBLE);}if ("0".equals(list.get(position).getLocktype())) {/判断是否上锁 String context = list.get(position).getContext();/定义正则表达式,用于匹配路径Pattern p = Pattern.compile("/([^\\.]*)\\.\\w{3}"); Matcher m = p.matcher (context);while (m.find()) {String path = m.group ().toString ();String type = path.substring (path.length() - 3, path.length());Bitmap bm = null;Bitmap rbm = null;if (holder.iv_img e.getDrawable() == null) {FileInputStream f;try {f = new FileInputStream(m.group ());BitmapFactory.Options options = newBitmapFactory.Options();options.inJustDecodeBounds = true;Bitmap bmp = BitmapFactory.decodeFile(m.group (), options);options.inSampleSize = options.outHeight / 100;options.inJustDecodeBounds = false;options.inDither = false;options.inPreferredConfig = null;options.inPurgeable = true;options.inInputShareable = true;bm = BitmapFactory.decodeFile(m.group (), options); } catch (FileNotFoundException e) {/ TODO Auto-generated catch blocke.printStackTrace();}holder.iv_img e.setVisibility (View.VISIBLE); holder.tv_note_title.setLines(1);/一行holder.iv_img e.setImageBitmap (bm); |
}}} else {/若上锁holder.tv_note_title.setVisibility (View.GONE);holder.iv_img e.setVisibility (View.VISIBLE);holder.iv_img e.setBackgroundResource(R.drawable.lock bg); }return convertView;} |
图 3-7-1 设置记事密码
图 3-7-2 加锁后主界面的变化
(8)selector 选择器
通过 Xml 方式实现状态选择器 ,然后将写好的 selector 选择器存在放 res - drawable 文件下。
部分核心代码:
表 3-7 navigationbar_setting.xml
//设置是否获得焦点状态,true 表示获得焦点,默认为 false ,表示未获得焦点 android:state_focused="true"android:drawable="@drawable/navigationbar_setting_pressed"//设置是否按压状态,一般在 true 时设置该属性,表示已按压状态,默认为 false android:state_pressed="true"android:drawable="@drawable/navigationbar_setting_default" |
(9)修改密码实现
在简介界面,点击隐蔽在右上角的灰色齿轮图标,即可进入修改密码的界面。
核心代码实现:
表 3-9-1 修改密码
public void onOk(View view){EditText oldT = (EditText)findViewById(R.id.editText3); EditText newT1 = (EditText)findViewById(R.id.editText4); EditText newT2 = (EditText)findViewById(R.id.editText5);String old = oldT.getText().toString ();String new1 = newT1.getText().toString ();String new2 = newT2.getText().toString ();String yuan = getPass();if(yuan.equals(old)){if(new1.equals(new2)){writePass(new1);/单独写出来Toast.makeText(XiugaimimaActivity.this,"密码修改成功 新密 码:"+new1,Toast.LENGTH LONG).show();XiugaimimaActivity.this.finish();}elseToast.makeText(XiugaimimaActivity.this,"两次密码不同 ",Toast.LENGTH LONG).show();}else{Toast.makeText(XiugaimimaActivity.this,"原始密码错误 ",Toast.LENGTH LONG).show();}} |
表 3-9-2 writePass 方法
public void writePass(String str) {String mi = str;File appDir = getFilesDir ();File f = new File(appDir, "abc.txt");FileOutputStream fstream = null;try {fstream = new FileOutputStream(f);fstream.write(mi.getBytes("UTF-8"));} catch (Exception e) {} finally { |
try {fstream.close();} catch (Exception e2) {}}} |
四、课程总结
时间过得真的很快,转眼间一学期的安卓学习已告一段落。这是门很有趣的 课,才接触到就很喜欢,用的语言也是熟悉的 java,而且能在虚拟机上看见自己 写的程序跑起来,甚至连接真机测试运行,这是以前想都不敢想的。
不过从一开始安装软件就不太顺利,看到 C 盘由于默认路径被塞得满满的, 就想把路径改到机械去,网上相关的博客倒是不少,不过介绍的版本都有点旧, 捣鼓半天还是给 AS 整崩掉,前前后后大概安装了 7 、8 次 AS ,最后一次安装熟 练的让人心痛哈哈,其实增加一个系统环境变量,几个 G 的avd 就会默认安装在 别的盘,Gradle 和 m2 也算是两个大头,转移的话不是不可以,不过后期跑的时 候还是小毛病不断,所以还是老实点吧。一开始初始化 build 因为被墙,也是转 圈圈好久,最怕的是转到最后还报错,也试过网上找免费的梯子,不过也不是很 好 用 。 最 让 我 惊 喜 的 是 偶 然 找 到 的 阿 里 云 仓 库 镜 像 , 只 要 在 gradle-wrapper.properties 中配置一下,绿色圈圈转的嗖嗖的。
再说说学习历程吧,一开始自己挺瓜皮的,不是犯方法的嵌套定义错误,就 是代码放的位置不对劲,老师也很耐心地给我一一指出这些低级错误,哪怕已经 下课也会再待一会来给我们解答。课后的话,边看 PPT 边回忆老师讲的这个方法 怎么调,这个函数应该放在什么前面,以及有关生命周期的理解。慢慢的摸到了 门路,也整明白两个 activity 间,通过 fragment 与 activity 下的 fragment 以及一 个 activity 下的两个 fragment 间穿数据,这三种交互模式,一下子豁然开朗。买 了那本厚厚的权威指南也是我提高的一个契机,不懂的不会的地方就反复看,反 复查资料,好记性不如烂笔头,当我再翻看书上一行一列间的笔记时,不敢说烂 熟于心,起码一下子就能有大致的印象。书上的交流网站 bignerdranch 也很好, 里面有着全世界正在学这本书的人,初学者遇到的问题总是相似的,如果百度不 到的话,去那里看看有时候会有意想不到的收获。
最后就是这次的大作业了,一开始真的觉得很难很难。之前每次是对已有的 程序进行补充完善,突然一下子要自己写一个独立的程序,并且要去实现各种功 能,感觉无从下手。其实一开始我也是准备用已有的 CriminalIntent 进行修改, 而且每次挑战练习我都有做,平时没事看书后面的美化部分还整了点花里胡哨的 在我的 CriminalIntent 上,我想改出来的作品应该不会太差。虽然期末时间真的 很紧,大作业也好报告也罢堆在了一起,不过我想做点和别人不一样的。可能是 兴趣使然,更多的是想挑战下自己吧,我开始捣鼓我自己的小记事本。一开始疯 狂看书,确实书上知识点都基本整明白了,但就是上不了手,轮到打代码的时候 脑子一片浆糊。后来改变了策略,去看博客上别人怎么写的,整体应该怎么架构, 也看了极客学院和黑马的一些视频。通过学习别人的 Demo ,造出自己的轮子, 我觉得这是我最大的思想转变。不同于上学期 java 考试这种理论性的东西,光 抱着看书就差不多。我现在觉得实现一个程序更多要从写开始,能写多少先写多 少,遇到问题懂得去学习别人是怎么解决的,找到适合自己且能理解的方法应用 上去,实在解决不了就试试换种方式,一定不能死磕一个小功能的实现或者传值 的无效(血与泪的教训)。后面其实上手以后,进度慢慢的就快了起来,整体架 构也有了,剩下的就是往里面加更多东西了。不过我觉得一个好习惯是把复用的 代码抽出来,不然一个类可能有很多方法堆在一起,出错根本找不到在那里,看 来看去会浪费大量时间。好在有 log.d 这么个 debug 功能,调试时候把一个大的 方法中每一小步都输出一个测试消息,这样看跟踪日志就很有针对性,不过也不
能整太多,不然太混乱了。
之后的学期会继续学习安卓高级,虽然在这次的大作业中已经涉及到了一些 皮毛,一通捣鼓下来也算是懂得原理并且用熟了,不过离了解底层的具体实现还 差的远。虽然安卓现在框架也蛮多的,像 andbase,XUtil 等只需调用封装好的类, 实现增删改查只需一行代码。不过就像上学期基础的 java 知识一样,越想走得 远对底层就要越了解,封装好的东西大家用熟了基本没差,个人能力的体现往往 在于这些编程思维,你需要尝试着去创造。不过这些离我还很遥远,希望接下来 的自己能够踏踏实实走好每一步,努力努力再努力。
相关推荐
- 墨尔本一华裔男子与亚裔男子分别失踪数日 警方寻人
-
中新网5月15日电据澳洲新快网报道,据澳大利亚维州警察局网站消息,22岁的华裔男子邓跃(Yue‘Peter’Deng,音译)失踪已6天,维州警方于当地时间13日发布寻人通告,寻求公众协助寻找邓跃。华...
- 网络交友须谨慎!美国犹他州一男子因涉嫌杀害女网友被捕
-
伊森·洪克斯克(图源网络,侵删)据美国广播公司(ABC)25日报道,美国犹他州一名男子于24日因涉嫌谋杀被捕。警方表示,这名男子主动告知警局,称其杀害了一名在网络交友软件上认识的25岁女子。雷顿警...
- 一课译词:来龙去脉(来龙去脉 的意思解释)
-
Mountainranges[Photo/SIPA]“来龙去脉”,汉语成语,本指山脉的走势和去向,现比喻一件事的前因后果(causeandeffectofanevent),可以翻译为“i...
- 高考重要考点:range(range高考用法)
-
range可以用作动词,也可以用作名词,含义特别多,在阅读理解中出现的频率很高,还经常作为完形填空的选项,而且在作文中使用是非常好的高级词汇。...
- C++20 Ranges:现代范围操作(现代c++白皮书)
-
1.引言:C++20Ranges库简介C++20引入的Ranges库是C++标准库的重要更新,旨在提供更现代化、表达力更强的方式来处理数据序列(范围,range)。Ranges库基于...
- 学习VBA,报表做到飞 第二章 数组 2.4 Filter函数
-
第二章数组2.4Filter函数Filter函数功能与autofilter函数类似,它对一个一维数组进行筛选,返回一个从0开始的数组。...
- VBA学习笔记:数组:数组相关函数—Split,Join
-
Split拆分字符串函数,语法Split(expression,字符,Limit,compare),第1参数为必写,后面3个参数都是可选项。Expression为需要拆分的数据,“字符”就是以哪个字...
- VBA如何自定义序列,学会这些方法,让你工作更轻松
-
No.1在Excel中,自定义序列是一种快速填表机制,如何有效地利用这个方法,可以大大增加工作效率。通常在操作工作表的时候,可能会输入一些很有序的序列,如果一一录入就显得十分笨拙。Excel给出了一种...
- Excel VBA入门教程1.3 数组基础(vba数组详解)
-
1.3数组使用数组和对象时,也要声明,这里说下数组的声明:'确定范围的数组,可以存储b-a+1个数,a、b为整数Dim数组名称(aTob)As数据类型Dimarr...
- 远程网络调试工具百宝箱-MobaXterm
-
MobaXterm是一个功能强大的远程网络工具百宝箱,它将所有重要的远程网络工具(SSH、Telnet、X11、RDP、VNC、FTP、MOSH、Serial等)和Unix命令(bash、ls、cat...
- AREX:携程新一代自动化回归测试工具的设计与实现
-
一、背景随着携程机票BU业务规模的不断提高,业务系统日趋复杂,各种问题和挑战也随之而来。对于研发测试团队,面临着各种效能困境,包括业务复杂度高、数据构造工作量大、回归测试全量回归、沟通成本高、测试用例...
- Windows、Android、IOS、Web自动化工具选择策略
-
Windows平台中应用UI自动化测试解决方案AutoIT是开源工具,该工具识别windows的标准控件效果不错,但是当它遇到应用中非标准控件定义的UI元素时往往就无能为力了,这个时候选择silkte...
- python自动化工具:pywinauto(python快速上手 自动化)
-
简介Pywinauto是完全由Python构建的一个模块,可以用于自动化Windows上的GUI应用程序。同时,它支持鼠标、键盘操作,在元素控件树较复杂的界面,可以辅助我们完成自动化操作。我在...
- 时下最火的 Airtest 如何测试手机 APP?
-
引言Airtest是网易出品的一款基于图像识别的自动化测试工具,主要应用在手机APP和游戏的测试。一旦使用了这个工具进行APP的自动化,你就会发现自动化测试原来是如此简单!!连接手机要进行...
- 【推荐】7个最强Appium替代工具,移动App自动化测试必备!
-
在移动应用开发日益火爆的今天,自动化测试成为了确保应用质量和用户体验的关键环节。Appium作为一款广泛应用的移动应用自动化测试工具,为测试人员所熟知。然而,在不同的测试场景和需求下,还有许多其他优...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)