Android 線程間通信


進程與線程的區別?

  在Android中,線程是跑在進程之中的,當手機打開一個APP就相當於打開了一個進程,比如:UI界面的更新,就是在主線程中完成的,我也可以自定義一些子線程來完成所需要的任務.

如何創建線程?創建線程的幾種方式?

  1.創建一個類繼承Thread類

  2.創建一個類實現Runnable接口

什么是多線程?

  線程是程序中一個單一的順序控制流程,在程序中同是運行多個線程完成不同的工作,稱為多線程

ANR的基礎知識及產生?

  ANR:application not responding :應用程序無響應

  產生的情況:1.主要類型按鍵或觸摸事件在特定的時間(5秒)內無響應

        2.BroadcastReceiver在特定事件(10秒)內無法處理完成

        3.小概率類型Service在特定事件內無法完成

線程的狀態:

  創建(new) ---->就緒(runnable)---->運行(running)---->阻塞(bloocked)----->消亡(dead)

  當線程滿足所需要運行的條件時,才能進入就緒狀態

  當線程就如就緒狀態后,不能馬上獲得cpu的執行時間,需要CPU進行資源分配

  當線程被中斷后執行完畢才會被消亡

線程的生命周期

 

注意:多線程會導致CPU資源分配的增加導致系統繁忙

多線程示例:售票

package com.hejun.ticket;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {
    final static String TAG = "MainActivity";
    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button = findViewById(R.id.strat_sale);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                SaleTickets saleTickets1 = new SaleTickets(4);
                SaleTickets saleTickets2 = new SaleTickets(3);
                SaleTickets saleTickets3 = new SaleTickets(2);
                SaleTickets saleTickets4 = new SaleTickets(2);
                saleTickets1.setName("售票窗口1");
                saleTickets2.setName("售票窗口2");
                saleTickets3.setName("售票窗口3");
                saleTickets4.setName("售票窗口4");
                saleTickets1.start();
                saleTickets2.start();
                saleTickets3.start();
                saleTickets4.start();

            }
        });
    }
    private class SaleTickets extends Thread{
        private int tickets;
        private SaleTickets(int tickets){
            this.tickets = tickets;
        }
        @Override
        public void run() {
            super.run();
            while(tickets>0){
                Sale();
            }
            Log.d(TAG, Thread.currentThread().getName()+ "的票售賣完了");
        }
        private void Sale(){
            tickets--;
            Log.d(TAG, Thread.currentThread().getName()+ "正在賣票,還剩下"+ tickets +"張票");
        }
    }
}

演示結果

  

線程間通信的相關組件

  1.Message :消息.其中包含了消息ID,消息處理對象以及處理數據,Message有MessagesQueue統一列隊,最終有Handle處理

  2.Handle:處理者,負責Message的發送及處理,實現handleMessage(Message msg)方法,對特定的MEssage進行處理

  3.MessagesQueue:消息隊列,用來存放Handle發送過來的消息,並按照先進先出規則執行

  4.Looper:消息泵,不斷的從MessagesQueue中抽取Message執行,一個MessagesQueue需要一個Looper

  5.Thread:線程,輔助調度整個消息循環,即消息循環執行的場所

關系:Handle looper  MessagesQueue是簡單的三角關系Looper和MessagesQueue是一一對應的

消息循環

  一個Message經由Handle發送到MessagesQueue隊列中,再由Looper不斷的從MessagesQueue抽取,又再一次回到Handle的環抱,實現線程間的通信

線程與更新

  在ui線程中,如果創建Handle是不傳入Looper對象,那么將直接使用UI\線程的Looer對象(系統已經幫我們自動創建了),在其他線程創建Handle如果不傳入Looper對象,那么Handle將不能接收處理消息,在這種情況下,通常的做法是:

在創建Handle之前,為該線程准備好一個Looper(Looper.prepare),然后讓這個Looper跑起來(Looper.loop),這樣Handle 才能正常工作;.

注意:Handle處理消息總是在創建Handler的線程中執行,而我們的消息處理,不乏UI的更新操作,不正確的線程直接更新UI將引發異常,因此,我們需要時刻關心Handler是在哪個線程中創建的.

SDk提供四中方式可以從其他線程中訪問UI線程

  1.Activity.runOnUiThread(Runnable)

  2.View.post(Runnable)

  3.View.postDelayed(Runnable,long)

  4.Handler

案例,從網上下載圖片並更新進度

package com.hejun.ticket;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.os.Trace;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class DownPicture extends AppCompatActivity {
    final static String address = "http://img4.imgtn.bdimg.com/it/u=1952016862,1880307894&fm=26&gp=0.jpg";
    private static final String TAG = "DownPicture";
    private Handler mMainHandler = null;
    private int progress;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down_picture);
        Button button = findViewById(R.id.button);
        final ImageView imageView = findViewById(R.id.img);
        button.setOnClickListener(new View.OnClickListener() {
            @SuppressLint("HandlerLeak")
            @Override
            public void onClick(View view) {
                final ProgressDialog progressDialog = new ProgressDialog(DownPicture.this);
                progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                progressDialog.setMessage("下載中");
                progressDialog.setMax(100);
                progressDialog.show();
                new Thread(new Down(),"下載圖片").start();
                mMainHandler = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                        switch (msg.what){
                            case 10010:
                                progressDialog.setProgress(msg.arg1);
                                break;
                            case 10011:
                                progressDialog.dismiss();
                                Bitmap bitmap = (Bitmap) msg.obj;
                                imageView.setImageBitmap(bitmap);
                                break;
                        }
                    }
                };
            }
        });
    }

    class Down implements Runnable {
    String fileName = "dowmPicture";
        @Override
        public void run() {
            try {
                URL url = new URL(address);
                HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
                httpURLConnection.setConnectTimeout(5000);
                httpURLConnection.setRequestMethod("GET");
                if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    InputStream inputStream = httpURLConnection.getInputStream();
                    OutputStream outputStream = openFileOutput(fileName, MODE_PRIVATE);
                    byte[] bytes = new byte[1024*1024];
                    int s = httpURLConnection.getContentLength();
                    int d = 0;
                    int curent = 0;
                    while ((d = inputStream.read(bytes)) != -1){
                        outputStream.write(bytes,0,s);
                        curent +=  d;
                        progress = (int) ((float)curent/s*100);
                        Log.d(TAG, "當前現在進度為" + progress);
                        SystemClock.sleep(40);
                        Message message  = new Message();
                        message.arg1 = progress;
                        message.what = 10010;
                        mMainHandler.sendMessage(message);
                    }
                    if (progress == 100){
                        Bitmap bitmap = BitmapFactory.decodeFile(getFileStreamPath(fileName).getAbsolutePath());
                        Message message  = new Message();
                        message.obj = bitmap;
                        message.what = 10011;
                        mMainHandler.sendMessage(message);
                    }


                    inputStream.close();
                    outputStream.close();
                    httpURLConnection.disconnect();
                }

            }
            catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM