常见问题总结
2018-03-05 本文已影响7人
ccccccal
handler机制,使用时一般会遇到的问题有
在子线程中handler使用handler.senMessage等方法发送消息到消息队列messagequeue,一个handler会对应产生一个looper,一个looper会对应一个消息队列,looper会反复对消息队列的轮询,如果查到消息,就把消息指定给对应创建消息的hander去处理。
- 通过Looper的prepare方法创建MessageQueue
- 通过loop方法找到和当前线程匹配的Looper对象me
- 从me中取出消息队列对象mQueue
- 在一个死循环中,从mQueue中取出Message对象
- 调用每个Message对象的msg.target.dispatchMesssge方法
- 也就是Handler的dispatchMessage 方法
- 在dispatchMessage 根据Message对象的特点执行特定的方法
注意问题:
子线程创建handler必须指定looper
1、创建一个HandlerThread,即创建了一个包含Looper的线程。
HandlerThread handlerThread = new HandlerThread(“HandlerThread”);
handlerThread.start(); //创建HandlerThread后一定要记得start()
2、获取HandlerThread的Looper
Looper looper = handlerThread.getLooper();
3、创建Handler,通过Looper初始化
Handler handler = new Handler(looper);
4.想让HandlerThread退出,则需要调用handlerThread.quit()
private HandlerThread handlerThread = new HandlerThread("handler thread");
handlerThread.start();
handler = new Handler(handlerThread.getLooper()){//现成的Looper
@Override
public void handleMessage(Message msg) {
System.out.println("currentThread->"+Thread.currentThread());
}
};
只能在UI线程更新界面吗
1、使用Handler
2、用Activity对象的runOnUiThread方法
3、View.post(Runnable r)
4、Broadcast子线程中发送广播,主线程中接收广播并更新UI
5、AsyncTask
class TestThread extends Thread{
@Override
public void run() {
Looper.prepare();
TextView tx = new TextView(MainActivity.this);
tx.setText("时间煮雨");
tx.setTextColor(getResources().getColor(R.color.white));
tx.setBackgroundColor(getResources().getColor(R.color.colorPrimary));
tx.setGravity(Gravity.CENTER);
WindowManager wm = MainActivity.this.getWindowManager();
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
250, 150, 200, 200, WindowManager.LayoutParams.FIRST_SUB_WINDOW,
WindowManager.LayoutParams.TYPE_TOAST, PixelFormat.OPAQUE);
wm.addView(tx, params);
Looper.loop();
}
}
android内存溢出OOM
- 图片过大
- 等比缩放
- 采用软应用
- 使用第三方框架
2.多次横竖屏切换 - 清单文件配置,保持activity的生命周期
3.数据库没有关闭游标
4.Bitmap对象不再使用时调用recycle()来释放对象。
android造成内存泄漏的常见原因以及会产生什么问题,以及处理方式有(android Profiler以及leakcanary进行检查)
- context
工具类持有activity对象,大部分都是static
2.内部类的种种问题
handler,thread以及dialog等
public class LeakActivity extends Activity {
/**
* 声明静态内部类不会持有外部类的隐式引用
*/
private static class MyHandler extends Handler {
private final WeakReference<SampleActivity> mActivity;
public MyHandler(SampleActivity activity) {
mActivity = new WeakReference<SampleActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
SampleActivity activity = mActivity.get();
if (activity != null) {
// ...
}
}
}
private final MyHandler mHandler = new MyHandler(this);
/**
* 这里的Runnable也是
* 声明静态内部类不会持有外部类的隐式引用
*/
private static final Runnable sRunnable = new Runnable() {
@Override
public void run() { /* ... */ }
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//10分钟之后发送消息
mHandler.postDelayed(sRunnable, 1000 * 60 * 10);
// 退回到上一个Activity
finish();
}
}
@Override
public void onDestroy() {
//简单粗暴
mHandler.removeMessages(message);
mHandler.removeCallbacks(Runnable);
mHandler.removeCallbacksAndMessages(null);
}
-
广播记得取消注册
-
数据库游标
-
Bitmap对象不再使用时调用recycle()来释放对象。
6.未关闭InputStream/OutputStream
activity的缓存
public void onSaveInstanceState(Bundle savedInstanceState){
savedInstanceState.putBoolean("MyBoolean",true);
saveInstanceState.putDouble("MyDouble",1.9);
savedInstanceState.putInt("MyInt",1);
savedInstanceState.putString("MyString","Android");
super.onSaveInstanceState(savedInstanceState);
}
public void onRestoreInstanceState(Bundle savedInstanceState){
super.onRestoreInstanceState(savedRestoreInstanceState);
boolean myBoolean = saveInstanceState.getBoolean("MyBoolean");
double myDouble = saveInstanceState.getDouble("MyDouble");
int myInt = saveInstanceState.getInt("MyInt");
}
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 当activity第一次被创建的时候为空
// 所以我们来判断一下
if(savedInstanceState != null){
savedInstanceState.getString("anAnt");
}
}