轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/52847872
本文出自【趙彥軍的博客】
- 概述
- 封裝嘗試
- Handler優化
- 線程優化
- 框架使用
- 參考資料
概述
在Android中會使用異步任務來處理耗時操作,避免出現界面卡頓的問題,當然到目前為止可以使用的異步任務框架有很多,比如:
封裝嘗試
既然是異步的框架,那么肯定是在子線程中,所以第一步我們用自定義的ThreadTask繼承Thread. 并且重寫里面的run方法。
package com.zyj.app;
/*** Created by ${zyj} on 2016/10/17.*/public class ThreadTask extends Thread {@Overridepublic void run() {
super.run();}
}
然后子線程需要把處理結果回調給主線程,我們需要定義3個方法:
package com.zyj.app;
import android.support.annotation.MainThread;
import android.support.annotation.WorkerThread;
/*** Created by ${zyj} on 2016/10/17.*/public
abstract class ThreadTask<T> extends Thread {@Overridepublic void run() {
super.run();}
/*** 任務開始之前調用,運行在主線程*/@MainThreadpublic void onStart(){ }
/*** 子線程中調用,運行在子線程* @return*/@WorkerThreadpublic
abstract T onDoInBackground() ;
/*** 子線程返回的結果,運行在主線程* @param t*/@MainThreadpublic void onResult( T t ){ }
}
另外子線程和主線程通信我們用的是Handler。Handler的初始化工作放在ThreadTask構造函數中完成。
private Handler handler ;
public ThreadTask(){handler =
new Handler( Looper.getMainLooper()){
@Overridepublic void handleMessage(Message msg) {
super.handleMessage(msg);}} ;}
最后還需要一個execute() 方法啟動線程。在啟動的前一刻最好調用Onstart方法。
/*** 開始執行*/public void execute(){onStart();start();}
最后一個完整的ThreadTask類是這樣的
package com.zyj.app;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.MainThread;
import android.support.annotation.WorkerThread;
/*** Created by ${zyj} on 2016/10/17.*/public
abstract class ThreadTask<T> extends Thread {private Handler handler ;public ThreadTask(){handler =
new Handler( Looper.getMainLooper()){
@Overridepublic void handleMessage(Message msg) {
super.handleMessage(msg);onResult((T) msg.obj);}} ;}
@Overridepublic void run() {
super.run();Message message = Message.obtain() ;message.obj = onDoInBackground() ;handler.sendMessage( message ) ;}
/*** 任務開始之前調用,運行在主線程*/@MainThreadpublic void onStart(){ }
/*** 子線程中調用,運行在子線程* @return*/@WorkerThreadpublic
abstract T onDoInBackground() ;
/*** 子線程返回的結果,運行在主線程* @param t*/@MainThreadpublic void onResult( T t ){ }
/*** 開始執行*/public void execute(){onStart();start();}
}
如何使用我們寫好的框架?
new ThreadTask<String>(){
@Overridepublic void onStart() {
super.onStart();Log.d(
"ThreadTask " ,
"onStart線程:" + Thread.currentThread().getName() ) ;}
@Overridepublic String
onDoInBackground() {Log.d(
"ThreadTask " ,
"onDoInBackground線程: " + Thread.currentThread().getName() ) ;
try {Thread.sleep(
3000 );}
catch (InterruptedException e) {e.printStackTrace();}
return "結果返回了";}
@Overridepublic void onResult(String s) {
super.onResult(s);Log.d(
"ThreadTask " ,
"onResult線程: " + Thread.currentThread().getName() +
" 結果:" + s ) ;}}.execute();
運行的結果:
ThreadTask: onStart線程:main
ThreadTask: onDoInBackground線程: Thread-229
ThreadTask: onResult線程: main 結果:結果返回了
Handler優化
到目前為止我們的框架初步就封裝好了,但是有沒有缺點呢,肯定是有的。首先每次創建一個ThreadTask的時候都會創建一個Handler,這顯然不是我們想看到的。
- 要保證Handler的實例的唯一性,可以用單例模式來獲取Handler
/*** 單例模式,保證handler只有一個實例* @return*/private static Handler
getHandler(){
if ( handler ==
null ){
synchronized ( MHandler.class ){
if ( handler ==
null ){handler=
new MHandler( Looper.getMainLooper()) ;}}}
return handler ;}
- MHandler是我們自定義的一個Handler類
private static class MHandler extends Handler {public MHandler( Looper looper ){
super( looper );}
@Overridepublic void handleMessage(Message msg) {
super.handleMessage(msg);ResultData resultData = (ResultData) msg.obj;resultData.threadTask.onResult( resultData.data );}}
/*** handler發送數據的實體* @param <Data>*/private static
class ResultData<Data>{ThreadTask threadTask ;Data data ;public ResultData( ThreadTask threadTask ,Data data ){
this.threadTask = threadTask ;
this.data = data ;}}
package com.zyj.app;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.MainThread;
import android.support.annotation.WorkerThread;
/*** Created by ${zyj} on 2016/10/17.*/public
abstract class ThreadTask<T> extends Thread {private static Handler handler ;public ThreadTask(){}
@Overridepublic void run() {
super.run();Message message = Message.obtain() ;message.obj =
new ResultData<T>(
this , onDoInBackground() ) ;getHandler().sendMessage( message ) ;}
/*** 任務開始之前調用,運行在主線程*/@MainThreadpublic void onStart(){ }
/*** 子線程中調用,運行在子線程* @return*/@WorkerThreadpublic
abstract T onDoInBackground() ;
/*** 子線程返回的結果,運行在主線程* @param t*/@MainThreadpublic void onResult( T t ){ }
/*** 開始執行*/public void execute(){onStart();start();}
/*** 單例模式,保證handler只有一個實例* @return*/private static Handler getHandler(){
if ( handler ==
null ){synchronized ( MHandler.
class ){if ( handler ==
null ){handler=
new MHandler( Looper.getMainLooper()) ;}}}
return handler ;}
private static
class MHandler extends Handler {public MHandler( Looper looper ){
super( looper );}
@Overridepublic void handleMessage(Message msg) {
super.handleMessage(msg);ResultData resultData = (ResultData) msg.obj;resultData.threadTask.onResult( resultData.data );}}
/*** handler發送數據的實體* @param <Data>*/private static
class ResultData<Data>{ThreadTask threadTask ;Data data ;public ResultData( ThreadTask threadTask ,Data data ){
this.threadTask = threadTask ;
this.data = data ;}}
}
到現在已經解決了Handler多次創建的問題,那么這個ThreadTask本質上還是新建線程來運行異步任務,為了避免不斷的創建線程,所以還需要一個線程池。
線程優化
/*** 線程池,創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。*/private static ExecutorService executorService = Executors.newFixedThreadPool(
15 ) ;
private void run() {executorService.execute(
new Runnable() {
@Overridepublic void run() {Message message = Message.obtain() ;message.obj =
new ResultData<T>( ThreadTask.
this , onDoInBackground() ) ;getHandler().sendMessage( message ) ;}});}
/*** 開始執行*/public void execute(){onStart();run();}
package com.zyj.app;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.MainThread;
import android.support.annotation.WorkerThread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/*** Created by ${zyj} on 2016/10/17.*/public
abstract class ThreadTask<T> {private static Handler handler ;
/*** 線程池,創建一個定長線程池,可控制線程最大并發數,超出的線程會在隊列中等待。*/private static ExecutorService executorService = Executors.newFixedThreadPool(
15 ) ;public ThreadTask(){}
private void run() {executorService.execute(
new Runnable() {
@Overridepublic void run() {Message message = Message.obtain() ;message.obj =
new ResultData<T>( ThreadTask.
this , onDoInBackground() ) ;getHandler().sendMessage( message ) ;}});}
/*** 任務開始之前調用,運行在主線程*/@MainThreadpublic void onStart(){ }
/*** 子線程中調用,運行在子線程* @return*/@WorkerThreadpublic
abstract T onDoInBackground() ;
/*** 子線程返回的結果,運行在主線程* @param t*/@MainThreadpublic void onResult( T t ){ }
/*** 開始執行*/public void execute(){onStart();run();}
/*** 單例模式,保證handler只有一個實例* @return*/private static Handler getHandler(){
if ( handler ==
null ){synchronized ( MHandler.
class ){if ( handler ==
null ){handler=
new MHandler( Looper.getMainLooper()) ;}}}
return handler ;}
private static
class MHandler extends Handler {public MHandler( Looper looper ){
super( looper );}
@Overridepublic void handleMessage(Message msg) {
super.handleMessage(msg);ResultData resultData = (ResultData) msg.obj;resultData.threadTask.onResult( resultData.data );}}
/*** handler發送數據的實體* @param <Data>*/private static
class ResultData<Data>{ThreadTask threadTask ;Data data ;public ResultData( ThreadTask threadTask ,Data data ){
this.threadTask = threadTask ;
this.data = data ;}}
}
框架使用
new ThreadTask<String>(){
@Overridepublic String
onDoInBackground() {
return "我是線程";}}.execute();
new MyTask().execute();
class MyTask extends ThreadTask<String> {@Override
public void onStart() {
super.onStart();}@Override
public String onDoInBackground() {
try {Thread.sleep(
2000);}
catch (InterruptedException e) {e.printStackTrace();}
return "ThreadTask" ;}@Override
public void onResult(String s) {
super.onResult(s);}}
參考資料
【1】Android AsyncTask 深度理解、簡單封裝、任務隊列分析、自定義線程池
【2】Android 自定義線程池的實戰
【3】Java 單例模式
【4】Android Handler、Loop 的簡單使用
【5】Android 更新UI的幾種方式
總結
以上是生活随笔為你收集整理的Android 从零开始打造异步处理框架的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。