Android编程权威指南(第2版)读书笔记

1.按键监听器

在按键监听器注册时匿名内部类中使用toast时注意,此时this是View.OnClickListener,而不是activity

2.有时,出于种种原因,可能需要脱离Android Studio编译代码。

要使用Gradle,请切换到项目目录并执行以下命令:
$ ./gradlew tasks
如果是Windows系统,执行以下命令:
> gradlew.bat tasks
执行以上命令会显示一系列可用任务。你需要的是任务是installDebug,因此,再执行以下
命令:
$ ./gradlew installDebug
如果是Windows系统,执行以下命令。
> gradlew.bat installDebug
以上命令将把应用安装到当前连接的设备上,但不会运行它。要运行应用,需要在设备上手
动启动。

3.设置自动识别前缀

首先,配置Android Studio识别成员变量的m前缀。
打开
Android Studio首选项对话框(Mac用户选择Android Studio菜单,Windows用户选择File →
Settings
菜单)。分别展开EditorCode Style选项,在Java选项下选择Code Generation选项页。
Naming表单中,选择Fields行,添加m作为fields的前缀,然后添加s作为StaticFields的前缀

4.控件继承关系

View->TextView->Button

View->ImageView->ImageButton

5.onCreate()方法生命周期相关

通常, activity通过覆盖onCreate(...)方法来准备以下用户界面相关的工作:
实例化组件并将组件放置在屏幕上(调用setContentView(int)方法);
引用已实例化的组件;
为组件设置监听器以处理用户交互;
访问外部模型数据。
千万不要自己去调用
onCreate(...)方法或任何其他Activity生命周期方法,记住这一点
很重要。我们只需在
activity子类里覆盖这些方法,Android会适时去调用它们。 

另外,在onCreate(...)方法里,必须首先调用超类的实现方法,然后再调用
其他方法,这一点很关键。而在其他几个方法中,是否首先调用超类方法就不那么重要了。

需要注意的是,停止的activity能够存在多久,谁也无法保证。系统需要回收内存时,它将首
先销毁那些停止的
activity 

系统重启或长时间不使用activity时,暂存的activity记录通常也会被清除,此时的保存在activity中的bundle中的数据也会消失
和单击主屏幕键不一样的是,单击后退键后,无论是否启用Don’t keep activities选项,系统
总是会销毁当前
activity。单击后退键相当于通知系统“用户不再需要使用当前的activity

6.设备旋转导致界面回到初始

在应用运行中,只要设备配置发生了改变,Android就会销毁当前activity,然后再
创建新的
activity

设备旋转时,系统会销毁当前QuizActivity实例,然后创建一个新的QuizActivity实例,重新调用oncreate调用新的布局文件。再
次旋转设备,查看该销毁与再创建的过程。

横屏activity的创建:

  1. New Android resource directory
  2. 从资源类型(Resource type)列表中选择layout,保持Source Setmain选项不变。接下来选中待选资源特征列表中的Orientation然后单击>>按钮将其移动至已选资源特征区域
  3. 确认选中Screen Orientation下拉列表中的Landscape选项,并确保目录名显示为layout-land,如图3-10所示。点击OK按钮让Android Studio创建res/layout-land 
  4. 在project视图下,activity_quiz.xml文件从res/layout目录复制至res/layout-land目录,两个布局文件必须具有相同的文件名,这样它们才能以同一个资源ID被引用。
  5. 修改layout-land下的布局文件,修改成framelayout,这个帧布局是使用android:layout_gravity来指定位置,因此每个framelayout的直属子类需要添加这个值
  6. 在activity中覆盖onSaveInstanceState,put键值对,在oncreate中获取和设置键值。
7. 显式intent

简单的方法是直接在数据目的activity中
Intent i = new Intent(QuizActivity.this, CheatActivity.class);
startActivity(i); 
带参数的intent
传递数据需要在数据目的activity加入
public static Intent newIntent(Context packageContext, boolean answerIsTrue) {
Intent i = new Intent(packageContext, CheatActivity.class);
i.putExtra(EXTRA_ANSWER_IS_TRUE, answerIsTrue);
return i;
} 
然后在数据源activity中调用这个方法,并且把数据answerIsTrue传递进去
Intent i = CheatActivity.newIntent(QuizActivity.this, answerIsTrue);
startActivityForResult(intent, REQUEST_CODE_CHEAT);
然后就可以在数据目的activity中获取
mAnswerIsTrue = getIntent().getBooleanExtra(EXTRA_ANSWER_IS_TRUE, false); 
处理返回值
发出返回值的activity首先设置数据isAnswerShown
private void setAnswerShownResult(boolean isAnswerShown) {
Intent data = new Intent();
data.putExtra(EXTRA_ANSWER_SHOWN, isAnswerShown);
setResult(RESULT_OK, data);
} 
其次设置静态解析方法
public static boolean wasAnswerShown(Intent result) {
return result.getBooleanExtra(EXTRA_ANSWER_SHOWN, false);
} 

接收返回值的activity覆盖onActivityResult
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK) {
return;
}
if (requestCode == REQUEST_CODE_CHEAT) {
if (data == null) {
return;
}
mIsCheater = CheatActivity.wasAnswerShown(data);
}
} 


8.创建UI fragment

创建UI fragment的步骤与创建activity的步骤相同,具体如下:
 通过定义布局文件中的组件,组装界面;
 创建fragment类并设置其视图为定义的布局;
 通过代码的方式,组装在布局文件中实例化的组件 


9.布局属性

android:padding和android:margin的区别

android:layout_marginLeft指该控件距离边父控件的边距,指定视图组件间的距离;

android:paddingLeft指该控件内部内容,如文本距离该控件的边距。指定视图外边框与其内容间的距离。

如:
当按钮分别设置以上两个属性时,得到的效果是不一样的。
android:paddingLeft="30px":
按钮上设置的内容(例如图片)离按钮左边边界30个像素。
android:layout_marginLeft="30px"
整个按钮离左边设置的内容30个像素
这二个属性是相对的,假设B是A的子控件,设置B的margin和设置A的padding能达到相同的效果。


layout_开头的属性作用于组件 

layout_开头的属性则作用于组件的父组件

10 .日期SimpleDateFormat 

// SimpleDateFormat 类的格式化字符:
// G 年代指示符(AD) 
// y 年(yy:10 y/yyy/yyyy:2010)
// M 月(M:1 MM:01 MMM:Jan MMMM:January MMMMM:J) 
// L 独立月(L:1 LL:01 LLL:Jan LLLL:January LLLLL:J) 
// d 一个月中的第几日(只需此一个字符,输出如:10)
// h 时(只需此一个字符,输出如:上/下午 1 ~ 12) 
// H 时(只需此一个字符,输出如:0 ~ 23) 
// k 一天中的第几个小时(只需此一个字符,输出如:1 ~ 24)
// K 时(上/下午 0 ~ 11)
// m 一小时中的第几分(只需此一个字符,输出如:30)
// s 一分钟中的第几秒(只需此一个字符,输出如:55)
// S 毫秒(只需此一个字符,输出如:978)
// E 星期几(E/EE/EEE:Tue, EEEE:Tuesday, EEEEE:T)
// c 独立星期几(c/cc/ccc:Tue, cccc:Tuesday, ccccc:T)
// D 一年中的第几天(只需此一个字符,输出如:189)
// F 一月中的第几个星期几(只需此一个字符,输出如:2)
// w 一年中的第几个星期(只需此一个字符,输出如:27)
// W 一月中的第几个星期(只需此一个字符,输出如:1)
// a 上/下午标记符(只需此一个字符,输出如:AM/PM)
// Z 时区(RFC822)(Z/ZZ/ZZZ:-0800 ZZZZ:GMT-08:00 ZZZZZ:-08:00)
// z 时区(z/zz/zzz:PST zzzz:Pacific Standard Time)

11.指定app登陆界面

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />


12.RecyclerView ViewHolder 和 Adapter 
RecyclerView 只创建刚好充满屏幕的12个视图,而不是100个视图。用户
滑动屏幕切换视图时,上一个视图会被回收利用。顾名思义, RecyclerView所做的就是回收再
利用,循环往复。 在oncreateview方法中会设置显示方式和绑定adapter和viewholder

adapter负责:
 创建必要的ViewHolder;
 绑定ViewHolder至模型层数据。 

ViewHolder只做一件事:容纳View视图


13.Android开发常用到单例的一大原因是

它们比fragment或activity活得久。例如,在设备旋转
或是在fragment和activity间跳转的场景下,单例不会受到影响,而旧的fragment或activity已经不
复存在了 

14.是否要保留fragment

首先,相比非保留fragment,保留fragment的显示非常复杂。一旦出现问题,排查起来非常
耗时。既然使用它会让程序复杂起来,能不用就不用吧。
其次,
fragment在使用保存实例状态savedInstanceState的方式处理设备旋转时,也能够应对所有生命周期场景;
但保留的
fragment只能处理activity因设备旋转而销毁的情况。如果activity是因操作系统需要回收
内存而被销毁,则所有保留的
fragment也会随之销毁,数据也就跟着丢失了。即使没有销毁,在activity实例进程关闭时,fragment也会被销毁,因此savedInstanceState保存的
时间更久一点。 

15.任务与后退栈

任务是用户比较关心的activity栈。栈底部的activity通常称为activity。用户可以看到栈顶的
activity。用户点击后退键时,栈顶activity会弹出栈外。如果当前屏幕上显示的是基activity,点击
后退键,系统会退回主屏幕。

在当前任务中启动 activity 的好处是,用户可以在任务内而不是在应用层级间导航返回
当前,从 NerdLauncher 启动的任何 activity(可能是别的应用的) 都会添加到 NerdLauncher 任务中

16.进程与任务
尽管存在未知的异常情况,但总的来说, Android 世界里的每个应用组件都仅与一个进程相
关联。应用伴随着自己的进程一起完成创建,该进程同时也是应用中所有组件的默认进程。

(虽然组件可以指派给不同的进程,但我们推荐使用默认进程。如果确实需要在不同进程中
运行应用组件,通常也可以借助多线程来达到目的。相比多进程的使用,
Android 多线程的使用
更加简单。)
每一个 activity 实例都仅存在于一个进程和一个任务中。这也是进程与任务的唯一相似之处。任
务只包含
activity ,这些 activity 通常来自于不同的应用;而进程则包含了应用的全部运行代码和对象。
进程与任务很容易让人混淆,主要原因在于它们不仅在概念上有某种重叠,而且通常都是以
其所属应用的名称被人提及的。例如,从
NerdLauncher 启动器中启动 CriminalIntent 应用时,操作
系统创建了一个
CriminalIntent 进程以及一个以 CrimeListActivity 为基 activity 的新任务。在
overview screen 中,我们可以看到标签为 CriminalIntent 的任务。

打开 CriminalIntent 应用,选择任何 crime 项,然后点击 CHOOSE SUSPECT 按钮。这会打开联
系人应用让我们选择目标联系人。随即,联系人
activity 会被加入 CriminalIntent 应用任务。如果此
时点击后退键在不同
activity 间切换的话,用户可能意识不到他们正在进程间切换。
然而,联系人
activity 实例确实是在联系人应用进程的内存空间创建的,而且也是在该应用进
程里的虚拟机上运行的。这可以从图
22-13 中看出。 

为进一步了解进程和任务的概念,让CriminalIntent应用处于运行状态,并打开联系人列表界
面。(继续之前,请确保联系人应用没有在overview screen出现。)点击主屏幕键回到主屏幕,从
中启动联系人应用。然后从联系人列表选取任意联系人,或添加新的联系人。
在这个操作过程中,会在联系人应用进程中创建新的联系人列表activity和联系人明细界面实
例。联系人应用新任务也会完成创建。这个新任务会引用联系人列表activity和联系人明细界面实
例,如图22-14所示。 


在发送crime消息时,你所选择发送消息应用的activity不会添加到
CriminalIntent应用任务中,而是添加到它自己的独立任务中
Lollipop设备上,对以android.intent.action.SENDaction.intent.action.SEND_
MULTIPLE
操作启动的activity,隐式intent选择器会创建独立的新任务。(在旧设备上,Gmail
activity是直接添加给CriminalIntent应用任务的。) 
Lollipop之前的设备上查看overview
screen
的话,你只能看到孤零零的一个任务。前面已说过, Lollipop之前的系统需要在manifest
提前定义应用任务,所以系统无法为单个应用动态创建多个任务。


17.线程
如果创建了大量的AsyncTask,或者长时间运行AsyncTask,那么很可能就是错用了它。
Android 3.2版本起,AsyncTask不再为每一个AsyncTask实例单独创建线程。相反,
它使用一个
Executor在单一的后台线程上运行所有AsyncTask后台任务。这意味着每个
AsyncTask都需要排队逐个运行。显然,长时间运行的AsyncTask会阻塞其他AsyncTask
时可使用Handler与主线程通信



第二遍总结:

1.Framelayout是最简单的layout,他是通过各个view的layout_gravity来确定位置。

2.startactivity并不是Activity的静态方法,他是通过交给操作系统的activityManager来启动别的应用,第一个参数指定要启动的activity在哪个包的content,并且通过getIntent() 获取startactivity传过来的intent。

3.显示intent主要用于同一应用中不同组件中。

4.调用Activity.finish()方法同样可以将CheatActivity从栈里弹出 。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值