編輯:關於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 ThreadTaskextends 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 ThreadTaskextends 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 ThreadTaskextends 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 ResultDataexecute() 方法( 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{ 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方式2(){ @Override public String onDoInBackground() { return "我是線程"; } }.execute();
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的一些簡單用法一直想寫一個關於 WebView 控件的 一些簡單運用,都沒什麼時間,這次也是擠出時間寫的,裡面的一些基礎知識就等有時間再更新
有很多情況下,我們只要運用好Android給我提供好的控件,經過布局巧妙的結合在一起,就是一個新的控件,我稱之為“自定義組合控件”。那麼,這種自定義組合控件在什麼情況下用
什麼是dex文件他是Android系統的可執行文件,包含應用程序的全部操作指令以及運行時數據。由於dalvik是一種針對嵌入式設備而特殊設計的java虛擬機,所以dex文
在你的手機更多設置或者高級設置中,我們會發現有個無障礙的功能,很多人不知道這個功能具體是干嘛的,其實這個功能是為了增強用戶界面以幫助殘障人士,或者可能暫時無法與設備充分交