Android學習筆記之多線程間的異步通信

添加一個按鈕,并指定一個按鈕的點擊事件:

public void btnClicked(){
    new Thread(new Runnable() {
        //模擬一個網(wǎng)絡(luò)請求事件
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            handler.sendEmptyMessage(1);
        }
    });
    //handler.sendEmptyMessageDelayed(1,2000);//兩秒后發(fā)送消息
}

定義一個Handler對象:

private Handler handler = new Handler(){
    //接收消息等待處理
    @Override
    public void handleMessage(Message msg) {
        //回到主線程
       switch (msg.what){
           case 1:
               button.setText("按鈕被改變了");
               break;
           default:
               break;
       }
    }
};

點擊了按鈕后,實現(xiàn)了按鈕的文字改變?yōu)橹付ǖ膬?nèi)容。因為UI控件的修改只能在主線程中執(zhí)行,所以當我們在自定義的子線程中修改按鈕的文字時會導(dǎo)致程序運行的崩潰。

使用Message類發(fā)送消息

Message message = new Message();
String str = "Message";
message.obj = str;
message.what = 2;
handler.sendMessage(message);

消息接收處理:

case 2:
       String str = (String) msg.obj;
       button.setText(str);
       break;

使用post方法

public void testPost(){
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //在非主線程中更新UI控件的內(nèi)容
            handler.post(new Runnable() {
                @Override
                public void run() {
                    button.setText("12df");
                }
            });
        }
    });
}

post的類方法允許排列一個Runnable對象到主線程中,等待執(zhí)行。

子線程中更新UI控件內(nèi)容的其他方法:

runOnUiThread(new Runnable() {
         @Override
        public void run() {
              button.setText("3dfs");
                }
         });  

view控件+post方法

button.post(new Runnable() {
       @Override
      public void run() {
            button.setText("sergs34");
            }
        });

AsyncTask異步任務(wù)類

/*AsyncTask的三個參數(shù)
* 參數(shù)一:執(zhí)行異步任務(wù)時需要傳入的三個的參數(shù),可用于在后臺任務(wù)中執(zhí)行
* 參數(shù)二:后臺任務(wù)執(zhí)行時,若需要在前臺顯示進度,則使用這里指定的參數(shù)作為進度單位
* 參數(shù)三:異步任務(wù)執(zhí)行結(jié)束后返回的結(jié)果
* */
class  TestTask extends AsyncTask<Void,Void,String>{
    //在異步線程里執(zhí)行
    @Override
    protected String doInBackground(Void... voids) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String string = "asyncTask";
        return  string;
    }
    //接收子線程返回的字符串,切換到主線程執(zhí)行
    @Override
    protected void onPostExecute(String s) {
        button.setText(s);
    }
}

AyncTask類常用的方法:

  • onPreExecute():在后臺異步任務(wù)執(zhí)行開始前調(diào)用;
  • doInBackground():該方法里所有的代碼都在自線程中執(zhí)行,常用來處理一些耗時的操作。任務(wù)結(jié)束后,返回執(zhí)行的結(jié)果也可以不返回(視類的第三個參數(shù)而定)。
  • onProgressUpdate():接收后臺publishProgress(int)方法傳遞的參數(shù),用來更新前臺的UI控件;
  • onPostExecute():后臺任務(wù)執(zhí)行接收后,根據(jù)后臺執(zhí)行返回的結(jié)果更新前臺的UI內(nèi)容。

應(yīng)用實例

.xml文件

     <Button
    android:id="@+id/btn"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="btnClicked"
    android:text="Hello World!" />  
     
    <ProgressBar
    android:id="@+id/pb"
    android:layout_width="match_parent"
    android:layout_height="20dp"
    android:layout_centerInParent="true"
    android:visibility="gone"
    android:max="100"
    style="?android:attr/progressBarStyleHorizontal"
    />

.java文件

    public class MainActivity extends AppCompatActivity {
      private Button button;
    private ProgressBar progressBar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    button = (Button) findViewById(R.id.btn);
    progressBar = (ProgressBar) findViewById(R.id.pb);
    }
        public void btnClicked(View view){
     new TestAsyncTask().execute();
    }
    
    class TestAsyncTask extends AsyncTask<Void,Integer,Boolean>{
    int pregress;
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Log.d("TAG","準備下載");
        progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    protected Boolean doInBackground(Void... voids) {
        Log.d("TAG","正在下載");
        try {
            while (true){
                //每隔一秒下載10%
                Thread.sleep(1000);
                pregress+=10;
                // 通知主線程當前進度是多少
                publishProgress(pregress);
                //退出永久循環(huán)
                if (pregress>=100){
                    break;
                }
            }
        }
        catch (Exception e){
             return false;
        }
        return true;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        Log.d("TAG","已下載"+values[0]+“%”);
        progressBar.setProgress(values[0]);
    }

    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        if (aBoolean){
            Log.d("TAG","下載成功");
            progressBar.setVisibility(View.GONE);//隱藏進度條
        }
        else {
            Log.d("TAG","下載失敗");

        }
      } 
     }
    }

終端輸出:

    03-28 18:37:34.840 619-619/com.example.felix.asynctaask D/TAG: 準備下載
    03-28 18:37:34.853 619-3897/com.example.felix.asynctaask D/TAG: 正在下載
    03-28 18:37:35.889 619-619/com.example.felix.asynctaask D/TAG: 已下載10%
    03-28 18:37:36.901 619-619/com.example.felix.asynctaask D/TAG: 已下載20%
    03-28 18:37:37.907 619-619/com.example.felix.asynctaask D/TAG: 已下載30%
    03-28 18:37:38.939 619-619/com.example.felix.asynctaask D/TAG: 已下載40%
    03-28 18:37:39.981 619-619/com.example.felix.asynctaask D/TAG: 已下載50%
    03-28 18:37:41.019 619-619/com.example.felix.asynctaask D/TAG: 已下載60%
    03-28 18:37:42.060 619-619/com.example.felix.asynctaask D/TAG: 已下載70%
    03-28 18:37:43.106 619-619/com.example.felix.asynctaask D/TAG: 已下載80%
    03-28 18:37:44.148 619-619/com.example.felix.asynctaask D/TAG: 已下載90%
    03-28 18:37:45.192 619-619/com.example.felix.asynctaask D/TAG: 已下載100%
    03-28 18:37:45.192 619-619/com.example.felix.asynctaask D/TAG: 下載成功
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容