1. Android基本架构
Android系统架构分为Application层、Framework层、Runtime&Library层以及Kernel层。
2. Activity生命周期
3. Fragment生命周期
4. Service生命周期
5. Android基本布局类型
1. FrameLayout
2. LinearLayout
3. AbsoluteLayout
4. RelativeLayout
5. TableLayout
6. Activity启动模式
1. standard
标准模式,创建新的Activity时,默认创建新的Activity实例并压入任务栈栈顶。
2. singleTop
栈顶复用模式,如果当前创建的Activity已经处于任务栈栈顶,则使用该栈顶实例,而不重新创建。Activity的onCreate/onStart/onResume方法不会被执行,onNewIntent方法会被回调。
3. singleTask
栈内复用模式,如果当前创建Activity在任务栈中已存在,则使用该实例,如该实例不处于栈顶,则将该实例调到栈顶并清空上面的其他实例。同样的,Activity的onCreate/onStart/onResume方法不会被执行,onNewIntent方法会被回调。
4. singleInstance
在启动的时候,会开启一个新的BackStack,这个BackStack里只有一个Activity的实例存在,并且把这个BackStack获得焦点。这是一种很极端的模式,它会导致整个设备的操作系统里,只会存在一个这个Activity示例,无论是从何处被启动的。
7. Activity的缓存方法
1. onSaveInstanceState(Bundle outState)
当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行。如:返回Launcher,打开新Activity,锁屏,屏幕方向切换等。
onSaveInstanceState()如果被调用,这个方法会在onStop()前被触发,但系统并不保证是否在onPause()之前或者之后触发。
2. onRestoreInstanceState (Bundle outState)
onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用。
onRestoreInstanceState在onstart之后执行。
8. View的缓存方法
1. onSaveInstanceState
@Override
protected Parcelable onSaveInstanceState() {
Bundle bundle = new Bundle();
Parcelable superData = super.onSaveInstanceState();
bundle.putParcelable("super_data", superData);
bundle.putParcelableArrayList("save_data", mRects);
return bundle;
}
2. onRestoreInstanceState
@Override
protected void onRestoreInstanceState(Parcelable state) {
Bundle bundle = (Bundle) state;
Parcelable superData = bundle.getParcelable("super_data");
mRects = bundle.getParcelableArrayList("save_data");
super.onRestoreInstanceState(superData);
}
9. Service启动方式
1. startService
StartService启动Service,首次启动会创建一个Service实例,依次调用onCreate()和onStartCommand()方法,此时Service进入运行状态,如果再次调用StarService启动Service,将不会再创建新的Service对象,系统会直接复用前面创建的Service对象,调用它的onStartCommand()方法。但是这样的Service与它的调用者无必然的联系,就是说当调用者结束了自己的生命周期,但是只要不调用stopService,那么Service还是会继续运行。无论启动了多少次Service的,只需调用一次stopService即可停掉Service。
Intent intent = new Intent(this, MyService.class);
//开启Service
startService(intent);
//关闭Service
stopService(intent);
2. bindService
private class MyServiceConnection implement ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder binder) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
ServiceConnection sc = new MyServiceConnection();
Intent intent = new Intent(this, MyService.class);
//开启Service
bindService(intent, sc, Context.BIND_AUTO_CREATE);
//关闭Service
unbindService(sc);
10. Service停止方式
Service停止有两种,一种是通过调用stopService()方法来停止,另一种是Service自身执行stopSelf()方法停止。
例如,写了一个后台Service在应用打开时自动清理缓存,结束后不停留在后台,这时就可以在onStartCommand()方法最后写上stopSelf(),如此就可以在清理工作结束后自动关闭Service。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//清理缓存
clearImageCache();
//停止Service
stopSelf();
return START_NOT_STICKY;
}
11. Intent传输的数据类型
1. 基本数据类型
2. 基本数据类型数组
3. String/CharSequence
4. String/CharSequence数组
5. Parcelable
6. Serializable
12. BroadcastReceiver注册方法
1. 静态注册
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<!-- 自定义广播 -->
<action android:name="com.demo.myaction"/>
<!-- 系统广播 -->
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
2. 动态注册
MyBroadcastReceiver receiver = new MyBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("com.demo.myaction");
filter.addAction("android.intent.action.BOOT_COMPLETED");
//注册
registerReceiver(receiver, filter);
//取消注册
unregisterReceiver(receiver);
13. ContentResolver
14. Animation
1. 补间动画 (TweenAnimation)
1)AlphaAnimation(透明度渐变)
fromAlpha :起始透明度
toAlpha:结束透明度
2)ScaleAnimation(缩放渐变)
fromXScale/fromYScale:沿着X轴/Y轴缩放的起始比例
toXScale/toYScale:沿着X轴/Y轴缩放的结束比例
pivotX/pivotY:缩放的中轴点X/Y坐标,即距离自身左边缘的位置,比如50%就是以图像的 中心为中轴点
3)TranslateAnimation(位移渐变)
fromXDelta/fromYDelta:动画起始位置的X/Y坐标
toXDelta/toYDelta:动画结束位置的X/Y坐标
4)RotateAnimation(旋转渐变)
fromDegrees/toDegrees:旋转的起始/结束角度
repeatCount:旋转的次数,默认值为0,代表一次,假如是其他值,比如3,则旋转4次 另外,值为-1或者infinite时,表示动画永不停止
repeatMode:设置重复模式,默认restart,但只有当repeatCount大于0或者infinite或-1时 才有效。还可以设置成reverse,表示偶数次显示动画时会做方向相反的运动!
5)AnimationSet(组合渐变)
2. 帧动画(FrameAnimation)
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item
android:drawable="@mipmap/img1"
android:duration="100" />
<item
android:drawable="@mipmap/img2"
android:duration="100" />
...
</animation-list>
3. 属性动画(PropertyAnimation)
1. ValueAnimator
2. ObjectAnimator
14. Android数据存储
1. SQLite
2. SharedPreference
SharedPreferences preferences = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
//存储数据
SharedPreferences.Editor editor = preferences.edit();
editor.putString("myKey", "myValue");
editor.commit();
//取出数据
preferences.getString("myKey", "defaultValue");
3. File(I/O)
4. ContentProvider
15. Assets数据访问
16. raw数据访问
17. Context总结
数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task。一般情况不推荐。
数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。
数字3:在receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。(可以无视)
注:ContentProvider、BroadcastReceiver之所以在上述表格中,是因为在其内部方法中都有一个context用于使用。重点看Activity和Application,可以看到,和UI相关的方法基本都不建议或者不可使用Application,并且,前三个操作基本不可能在Application中出现。实际上,只要把握住一点,凡是跟UI相关的,都应该使用Activity做为Context来处理;其他的一些操作,Service,Activity,Application等实例都可以,当然了,注意Context引用的持有,防止内存泄漏。
18. IntentService
19. Bitmap的使用
InputSream is;
BitmapFactory.Options options = new BitmapFactory.Options();
//当这个参数为true的时候,意味着你可以在解析时候不申请内存的情况下去获取Bitmap的宽和高
//这是调整Bitmap Size一个很重要的参数设置
options.inJustDecodeBounds = true;
//这时候decode得到的bitmap为null,只是把图片的宽高放在Options里
BitmapFactory.decodeStream(is, null, options);
//获取合适的inSampleSize
options.inSampleSize = simpleSize;
//当你希望得到Bitmap实例的时候,不要忘了将这个参数设置为false
options.inJustDecodeBounds = false;
//这时候decode得到的才是真正的bitmap实例
Bitmap bitmap = BitmapFactory.decodeStream(is,null,options);
20. View
21. ViewGroup
22. AsyncTask用法
AsyncTask用于执行异步任务。
//三种泛型类型分别表示:启动任务执行的输入参数、后台任务执行的进度、后台计算结果的类型
private class MyAsyncTask extends AsyncTask<Integer, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
//任务执行前的准备操作
Log.d(TAG, "onPreExecute, start AsyncTask");
}
@Override
protected String doInBackground(Integer... params) {
//在此方法中执行耗时操作
Log.d(TAG, "doInBackgound");
int count = params[0];//取得execute方法传递过来参数的第一个(可传递多个)
while (count > 0) {
Log.d(TAG, "D-" + count);
//用于发送任务执行进度以更新UI
publishProgress(count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
}
return "D-DAY";
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
//doInBackground方法返回的结果传到此方法中
//任务结束后将接收到的结果直接将结果显示到UI组件上
Log.d(TAG, "doInBackground done. get result = " + s);
tv.setText(s);
}
@Override
protected void onProgressUpdate(Integer... values) {
//此方法在publishProgress()被调用以后被执行,用于直接将进度信息更新到UI组件上
super.onProgressUpdate(values);
tv.setText("D-" + values[0]);
}
}
//AsyncTask执行方式
MyAsyncTask asyncTask = new MyAsyncTask();
asyncTask.execute(10);//此处可传递N个指定类型的参数
23. Touch事件分发机制
Touch事件有关的处理方法主要由三个
//分派事件
public boolean dispatchTouchEvent(MotionEvent ev)
//拦截事件
public boolean onInterceptTouchEvent(MotionEvent ev)
//处理事件
public boolean onTouchEvent(MotionEvent event)
事件 | 含义 |
---|---|
dispatchTouchEvent | 用来分派事件。其中调用了onInterceptTouchEvent()和onTouchEvent(),一般不重写该方法 |
onInterceptTouchEvent | 用来拦截事件。ViewGroup类中的源码实现就是{return false;}表示不拦截该事件,事件将向下传递(传递给其子View);若手动重写该方法,使其返回true则表示拦截,事件将终止向下传递,事件由当前ViewGroup类来处理,就是调用该类的onTouchEvent()方法 |
onTouchEvent | 用来处理事件。返回true则表示该View能处理该事件,事件将终止向上传递(传递给其父View);返回false表示不能处理,则把事件传递给其父View的onTouchEvent()方法来处理 |
24. Android ANR
ANR表示Application Not Responding。发生ANR主要有以下三种情形:
- 主线程对输入事件5秒内没有处理完毕
- 主线程在执行BroadcastReceiver的onReceive()函数时10秒内没有处理完毕
- 主线程在Service的各个生命周期函数时20秒内没有处理完毕。
如何避免程序发生ANR:
- UI线程尽量只做跟UI相关的工作
- 耗时的操作(比如数据库操作,I/O,连接网络或者别的有可能阻塞UI线程的操作)把它放在单独的线程处理
- 尽量用Handler来处理UIThread和别的Thread之间的交互
25. OOM
OOM表示Out Of Memory。
26. Fragment的使用
app包中的fragment和v4包中的fragment的使用的区别:
- Fragment是在3.0之后才有的,支持的版本太高,在低版本中无法使用
- android.support.v4.app.Fragment可以兼容到1.6的版本
- Fragment的FragmentManager通过getFragmentManager()得到
- v4.app.Fragment的FragmentManager通过getSupportedFragmentManager()获取
27. Fragment与Activity的交互
1. onAttach(Context context)方法
添加v4.app.Fragment需要用v4.app.FragmentActivity或v7.app.AppCompatActivity。
Activity部分实现
//实现Fragment中定义的参数传递借口
public class MainActivity extends AppCompatActivity implements MainFragment.FragmentMessageListener {
public static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//添加Fragment并传递数据
Bundle bundle = new Bundle();
bundle.putString("myKey", "myValue");
MainFragment mainFragment = new MainFragment();
mainFragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction()
.add(mainFragment, "mainFragment")
.commit();
}
@Override
public void getMsgFromFragment(String msg) {
//此处接收Fragment传递过来的数据
Log.d(TAG, "Message sent from fragment received. msg = " + msg);
}
}
Fragment部分实现
public class MainFragment extends Fragment {
public static final String TAG = MainFragment.class.getSimpleName();
//定义一个用于传输数据的接口
public interface FragmentMessageListener {
void getMsgFromFragment(String msg);
}
private FragmentMessageListener msgListener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
//绑定实现数据传输接口的Activity
msgListener = (FragmentMessageListener) context;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//获取Activity传递过来的参数
Bundle bundle = getArguments();
Log.d(TAG, "Arguments sent from Activity is = " + bundle.getString("myKey"));
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.activity_main, null);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//通过接口向Activity传递数据
msgListener.getMsgFromFragment("Fragment.onActivityCreated");
}
}
2. Fragment发送广播
在Activity中注册广播接收器,从Fragment发送消息广播。
Intent intent = new Intent();
intent.setAction(MainActivity.ACTION_NAME);
intent.putExtra("msg", "Fragment Message");
getActivity().sendBroadcast(intent);