編輯:關於Android編程
在Android中會使用異步任務來處理耗時操作,避免出現界面卡頓的問題,當然到目前為止可以使用的異步任務框架有很多,比如:
直接 new Thread() 用Android自帶的AsyncTask 用RxJava等等
今天我們就來自己嘗試寫一個異步任務處理框架,代碼的設計思路參考AsyncTask
既然是異步的框架,那麼肯定是在子線程中,所以第一步我們用自定義的ThreadTask繼承Thread. 並且重寫裡面的run方法。
package com.zyj.app;
/**
* Created by ${zyj} on 2016/10/17.
*/
public class ThreadTask extends Thread {
@Override
public void run() {
super.run();
}
}
然後子線程需要把處理結果回調給主線程,我們需要定義3個方法:
onStart 任務開始之前調用,運行在主線程。可以做顯示進度條或者加載動畫。 onDoInBackground 異步任務執行,運行在子線程。可以做耗時操作。onResult 異步任務處理的結果,運行在主線程。
onDoInBackground這個方法是要在子類中實現的,所以要寫成抽象的方法,那麼ThreadTask類自然也要寫成抽象類。同時這個方法會返回異步處理結果,這個結果的類型需要寫成泛型,以便在子類中靈活運用。
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 extends Thread {
@Override
public void run() {
super.run();
}
/**
* 任務開始之前調用,運行在主線程
*/
@MainThread
public void onStart(){ }
/**
* 子線程中調用,運行在子線程
* @return
*/
@WorkerThread
public abstract T onDoInBackground() ;
/**
* 子線程返回的結果,運行在主線程
* @param t
*/
@MainThread
public void onResult( T t ){ }
}
另外子線程和主線程通信我們用的是Handler。Handler的初始化工作放在ThreadTask構造函數中完成。
private Handler handler ;
public ThreadTask(){
handler = new Handler( Looper.getMainLooper()){
@Override
public 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 extends Thread {
private Handler handler ;
public ThreadTask(){
handler = new Handler( Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//在這裡接收子線程發過來的消息
onResult((T) msg.obj);
}
} ;
}
@Override
public void run() {
super.run();
Message message = Message.obtain() ;
message.obj = onDoInBackground() ;
handler.sendMessage( message ) ;
}
/**
* 任務開始之前調用,運行在主線程
*/
@MainThread
public void onStart(){ }
/**
* 子線程中調用,運行在子線程
* @return
*/
@WorkerThread
public abstract T onDoInBackground() ;
/**
* 子線程返回的結果,運行在主線程
* @param t
*/
@MainThread
public void onResult( T t ){ }
/**
* 開始執行
*/
public void execute(){
onStart();
start();
}
}
如何使用我們寫好的框架?
new ThreadTask(){
@Override
public void onStart() {
super.onStart();
Log.d( "ThreadTask " , "onStart線程:" + Thread.currentThread().getName() ) ;
}
@Override
public String onDoInBackground() {
Log.d( "ThreadTask " , "onDoInBackground線程: " + Thread.currentThread().getName() ) ;
//模擬耗時操作
try {
Thread.sleep( 3000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
return "結果返回了";
}
@Override
public 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 結果:結果返回了
到目前為止我們的框架初步就封裝好了,但是有沒有缺點呢,肯定是有的。首先每次創建一個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 );
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//在這裡接收子線程發過來的消息
ResultData resultData = (ResultData) msg.obj;
resultData.threadTask.onResult( resultData.data );
}
}
ResultData是一個消息實體
/**
* handler發送數據的實體
* @param
*/
private static class ResultData{
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 extends Thread {
private static Handler handler ;
public ThreadTask(){
}
@Override
public void run() {
super.run();
Message message = Message.obtain() ;
message.obj = new ResultData( this , onDoInBackground() ) ;
getHandler().sendMessage( message ) ;
}
/**
* 任務開始之前調用,運行在主線程
*/
@MainThread
public void onStart(){ }
/**
* 子線程中調用,運行在子線程
* @return
*/
@WorkerThread
public abstract T onDoInBackground() ;
/**
* 子線程返回的結果,運行在主線程
* @param t
*/
@MainThread
public 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 );
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//在這裡接收子線程發過來的消息
ResultData resultData = (ResultData) msg.obj;
resultData.threadTask.onResult( resultData.data );
}
}
/**
* handler發送數據的實體
* @param
*/
private static class ResultData{
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 ) ;
修改run()方法。
private void run() {
executorService.execute(new Runnable() {
@Override
public void run() {
Message message = Message.obtain() ;
message.obj = new ResultData( ThreadTask.this , onDoInBackground() ) ;
getHandler().sendMessage( message ) ;
}
});
}
execute() 方法
/**
* 開始執行
*/
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 {
private static Handler handler ;
/**
* 線程池,創建一個定長線程池,可控制線程最大並發數,超出的線程會在隊列中等待。
*/
private static ExecutorService executorService = Executors.newFixedThreadPool( 15 ) ;
public ThreadTask(){
}
private void run() {
executorService.execute(new Runnable() {
@Override
public void run() {
Message message = Message.obtain() ;
message.obj = new ResultData( ThreadTask.this , onDoInBackground() ) ;
getHandler().sendMessage( message ) ;
}
});
}
/**
* 任務開始之前調用,運行在主線程
*/
@MainThread
public void onStart(){ }
/**
* 子線程中調用,運行在子線程
* @return
*/
@WorkerThread
public abstract T onDoInBackground() ;
/**
* 子線程返回的結果,運行在主線程
* @param t
*/
@MainThread
public 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 );
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//在這裡接收子線程發過來的消息
ResultData resultData = (ResultData) msg.obj;
resultData.threadTask.onResult( resultData.data );
}
}
/**
* handler發送數據的實體
* @param
*/
private static class ResultData{
ThreadTask threadTask ;
Data data ;
public ResultData( ThreadTask threadTask ,Data data ){
this.threadTask = threadTask ;
this.data = data ;
}
}
}
new ThreadTask(){
@Override
public String onDoInBackground() {
return "我是線程";
}
}.execute();
方式2
new MyTask().execute();
class MyTask extends ThreadTask {
@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);
}
}
Android中WebView的一些簡單用法
Android中WebView的一些簡單用法一直想寫一個關於 WebView 控件的 一些簡單運用,都沒什麼時間,這次也是擠出時間寫的,裡面的一些基礎知識就等有時間再更新
Android中View自定義組合控件的基本編寫方法
有很多情況下,我們只要運用好Android給我提供好的控件,經過布局巧妙的結合在一起,就是一個新的控件,我稱之為“自定義組合控件”。那麼,這種自定義組合控件在什麼情況下用
Dex文件格式詳解
什麼是dex文件他是Android系統的可執行文件,包含應用程序的全部操作指令以及運行時數據。由於dalvik是一種針對嵌入式設備而特殊設計的java虛擬機,所以dex文
Android AccessibilityService實現微信搶紅包插件
在你的手機更多設置或者高級設置中,我們會發現有個無障礙的功能,很多人不知道這個功能具體是干嘛的,其實這個功能是為了增強用戶界面以幫助殘障人士,或者可能暫時無法與設備充分交