1. 程式人生 > >Android多執行緒-----非同步的幾種方法

Android多執行緒-----非同步的幾種方法

在Android專案中,有經驗的開發人員都知道,一些耗時的IO操作等都必須在子執行緒中去操作,那麼可以有哪些方法來開啟子執行緒呢,一般可以使用Java中自帶的幾種方法,也可以使用Andorid特有的一些類。

用Java來實現非同步
主要有兩種方法來實現非同步,繼承Thread類和實現Runnable介面

1.繼承Thread類

public class MyThread extends Thread {

    private String name;

    public MyThread(String name){
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name);
    }
}
public class MainTest {

    public static void main(String[] args){

        MyThread myThread1 = new MyThread("myThread1");
        MyThread myThread2 = new MyThread("myThread2");
        MyThread myThread3 = new MyThread("myThread3");

        myThread1.start();
        myThread2.start();
        myThread3.start();
    }
}


MyThread繼承自Thread類,重寫run()方法,在run()方法中寫上子執行緒需要執行的任務就可以了。然後在測試的main()方法中new MyThread()。再呼叫start()方法。這樣就完成了使用繼承Thread,來實現子執行緒從建立到執行的整個過程。

2.實現Runnable介面

public class MyThreadRunnable implements Runnable {
    private String name;

    public MyThreadRunnable(String name){
        this.name = name;
    }

    @Override
    public void run() {
        System.out.println(name);
    }
}

public class MainTest {

    public static void main(String[] args){

        MyThreadRunnable r1 = new MyThreadRunnable("r1");
        MyThreadRunnable r2 = new MyThreadRunnable("r1");
        MyThreadRunnable r3 = new MyThreadRunnable("r1");

        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);
        Thread t3 = new Thread(r3);

        t1.start();
        t2.start();
        t3.start();
    }
}

new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("xxxx");
            }
        }).start();


MyThreadRunnable實現Runnable介面,並且在run()方法中實現自己的任務,這跟前面的很類似,只是後面要開啟執行緒的時候不僅需要new MyThreadRunnable()而且還需要new Thread()並且把前面的物件傳入,再通過Thread呼叫start()方法來啟動執行緒。 
上面的方法來開啟子執行緒,還可以用靜態內部類來實現,這樣程式碼看起來會更加簡潔。

從程式碼層面來看,繼承Thread看起來更加方便,但是java是單繼承的,在實際生產中,一般都需要某個類,所以實現Runnable的用法會多一點。

使用Android特有的方法來實現非同步


3.AsyncTask

AsyncTask 類允許你方便正確地使用UI執行緒(Android中的工作者執行緒主要有AsyncTask、IntentService、HandlerThread,它們本質上都是對執行緒或執行緒池的封裝。)。該類可以將耗時的操作放在後臺來處理,而不需要人為地另開執行緒或者使用handlers來完成。

當需要開闢一個後臺執行緒並且其執行結果需要反映到UI執行緒的時候,AsyncTask就派上用場了。定義一個AsyncTack時,需要指定3種類型(Params,Progress,Result),完成4個步驟(begin,doInBackground,processProgress,end)。
 

public class MainActivity extends Activity {


    private ProgressBar mProgressBar;
    private ImageView mImageView;

    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);


        MyAsyncTask myAsyncTask = new MyAsyncTask();
        myAsyncTask.execute("www.baidu.com/xxx.jpg");
    }

    class MyAsyncTask extends AsyncTask<String, Integer, Bitmap>{

        @Override
        protected void onPreExecute() {
            //這裡是開始執行緒之前執行的,是在UI執行緒
            mProgressBar.setMax(100);
            super.onPreExecute();
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            //這是在後臺子執行緒中執行的
            Bitmap bitmap = null;
            try {
                URL url = new URL(params[0]);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                InputStream inputStream = connection.getInputStream();
                bitmap = BitmapFactory.decodeStream(inputStream);
                publishProgress(70);//這裡是更新進度
                inputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bitmap;
        }

        @Override
        protected void onCancelled() {
            //當任務被取消時回撥
            super.onCancelled();
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            //更新進度
            mProgressBar.setProgress(values[0]);
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            super.onPostExecute(bitmap);
            //當任務執行完成是呼叫,在UI執行緒
            mImageView.setImageBitmap(bitmap);
        }
    }

}


MyAsyncTask基礎自AsyncTask,三個泛型分別為,String:是傳入引數型別,可以傳多個,Integer:是進度顯示的引數型別,也可以傳多個,Bitmap:是任務執行完的返回型別,這裡就是返回一個Bitmap。 
使用AsyncTask來實現非同步的有點就是簡單便捷,各個過程都有明確的回撥,過程可控。但是缺點就是要是執行多個非同步,就會變得很複雜。

4.Handler

public class HandlerTestActivity extends Activity {

    Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            int what = msg.what;
            if(what == 0){
                //在主執行緒中需要執行的操作,一般是UI操作
            }
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                //在子執行緒中執行任務,執行完成或需要通知UI執行緒時呼叫以下方法
                mHandler.sendEmptyMessage(0);
            }
        });
        thread.start();
    }
}

上面就是最簡單的使用Handler完成子執行緒和主執行緒的通訊(子執行緒發訊息給主執行緒)

public class LooperThreadActivity extends Activity {

    private Handler mHandler = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new MyThread().start();
        //發訊息到目標子執行緒
        mHandler.obtainMessage(0).sendToTarget();

    }

    class MyThread extends Thread{

        @Override
        public void run() {
            super.run();
            //1.建立訊息迴圈,初始化Looper
            Looper.prepare();
            mHandler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    int what = msg.what;
                    if(what == 0){
                        //
                    }
                }
            };
            //啟動訊息迴圈
            Looper.loop();
        }
    }
}

上面是主執行緒發訊息給子執行緒,也是比較類似的,只不過在子執行緒中,需要初始化Looper.prepare()和Looper.loop()。

5、RxJava

public class RxJavaTestActivity extends Activity {

    private ImageView mImageView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Observable.just("")
                .map(new Func1<String, Bitmap>() {
                    @Override
                    public Bitmap call(String s) {
                        //可以在這裡執行耗時操作,比如下載網路圖片,然後轉化為Bitmap
                        return null;
                    }
                }).subscribeOn(Schedulers.io())//把工作執行緒指定為了IO執行緒
                .observeOn(AndroidSchedulers.mainThread())//把回撥執行緒指定為了UI執行緒
                .subscribe(new Action1<Bitmap>() {
                    @Override
                    public void call(Bitmap bitmap) {
                        //這裡是在UI執行緒,這裡顯示了圖片
                        mImageView.setImageBitmap(bitmap);
                    }
                });
    }
}


這個比較新,學習路線比較陡峭,但是一旦入門,使用起來真的很爽。的使用了RxJava,來實現非同步操作。RxJava還有更多更強大的功能等你去發現。


原文:https://blog.csdn.net/u011803341/article/details/52774867