1. 程式人生 > >Android通訊模組(單執行緒,多執行緒通訊方式,Handler 與UI Thread的互動,Handler接合子執行緒的使用)

Android通訊模組(單執行緒,多執行緒通訊方式,Handler 與UI Thread的互動,Handler接合子執行緒的使用)

一丶概述

本週的學習計劃是Android通訊模組,內容:單執行緒,多執行緒通訊方式,Handler 與UI Thread的互動,Handler接合子執行緒的使用。

二丶效果演示(原始碼連結見文末)


三丶實現功能

1.演示使用Handler常見崩潰

2.handler更新TextView的UI

3.實現圖片輪播及停止

4.輸出handleMessage(Message mes)的mes列印

5.自定義執行緒相關handler測試執行

6.Handler非同步訊息處理測試

handler相關方法運用

四丶正文

1.選說說多執行緒(工作到現在用的不太多,都是別人封裝好的框架直接用)

2.Handler

最初學習Handler是通過扣丁學堂,之前的文章:扣丁學堂——Handler

最近開發用到的SwipeRefreshLayout 的onRefresh()方法,也常看到handler

@Override
public void onRefresh() {
    new Handler().postDelayed(new Runnable() {
        @Override
public void run() {
            mEntities.clear();
intData();
//★3.通知recycleView改變了資料
homeAdapter.notifyDataSetChanged();
//★4.記得關閉重新整理,否則重新整理球一直在轉 mSwipeRefreshLayout.setRefreshing(false); } }, 50); }
以上基本是在整理文章前關於handler的所有運用。

好了,現在重新認識

2.Handler類的引入:

3.Handler的執行流程圖:

流程圖解析: 
相關名詞

  • UI執行緒:就是我們的主執行緒,系統在建立UI執行緒的時候會初始化一個Looper物件,同時也會建立一個與其關聯的MessageQueue;
  • Handler:作用就是傳送與處理資訊,如果希望Handler正常工作,在當前執行緒中要有一個Looper物件
  • Message
    :Handler接收與處理的訊息物件
  • MessageQueue:訊息佇列,先進先出管理Message,在初始化Looper物件時會建立一個與之關聯的MessageQueue;
  • Looper:每個執行緒只能夠有一個Looper,管理MessageQueue,不斷地從中取出Message分發給對應的Handler處理!

簡單點說:

當我們的子執行緒想修改Activity中的UI元件時,我們可以新建一個Handler物件,通過這個物件向主執行緒傳送資訊;而我們傳送的資訊會先到主執行緒的MessageQueue進行等待,由Looper按先入先出順序取出,再根據message物件的what屬性分發給對應的Handler進行處理!

4.Handler的相關方法:

  • void handleMessage(Message msg):處理訊息的方法,通常是用於被重寫!
  • sendEmptyMessage(int what):傳送空訊息
  • sendEmptyMessageDelayed(int what,long delayMillis):指定延時多少毫秒後傳送空資訊
  • sendMessage(Message msg):立即傳送資訊
  • sendMessageDelayed(Message msg):指定延時多少毫秒後傳送資訊
  • final boolean hasMessage(int what):檢查訊息佇列中是否包含what屬性為指定值的訊息 
    如果是引數為(int what,Object object):除了判斷what屬性,還需要判斷Object屬性是否為指定物件的訊息

5.看程式碼

1.非UI執行緒執行緒更新UI崩潰測試:
case R.id.id_btn1:
    new Thread() {
        @Override
public void run() {
            try {
                Thread.sleep(1000 * 3);
idTv.setText("蹦啦");
} catch (InterruptedException e) {
                e.printStackTrace();
}
        }
    }.start();
    break;
case R.id.id_btn2:
    new Thread() {
        @Override
public void run() {
            try {
                Thread.sleep(1000 * 3);
handler.post(new Runnable() {
                    @Override
public void run() {
                        idTv.setText("又長帥了");
}
                });
} catch (InterruptedException e) {
                e.printStackTrace();
}
        }
    }.start();
    break;

關於這裡有個小插曲,涉及原始碼解讀,觀看愛哥部落格

2.迴圈播放圖片及停止

Handler handler = new Handler();
Thread myThread = new Thread(){
    @Override
public void run() {
        index++;
index = index%3;
System.out.println(index);
idImg.setImageResource(images[index]);
handler.postDelayed(myThread,1000);
}
};
點選事件
case R.id.id_btn3:
    handler.postDelayed(myThread,1000);
    break;
case R.id.id_btn4:
    handler.removeCallbacks(myThread);

handler.postDelayed(X,X)是延遲執行執行緒

handler.removeCallbacks(X)移除執行緒中所有訊息和回撥

3.handle傳遞message可攜帶的內容有(int 實體內等)

Handler customHander = new Handler() {
    @Override
public void handleMessage(Message msg) {
        idTv.setText("msg.arg1>"+msg.arg1+ "\nmsg.arg2>" +msg.arg2 +"\nmsg.obj>"+((Person)msg.obj).toString());
}
};
點選事件
            case R.id.id_btn5:
                Person dog=new Person("金三胖",1);
//                Message message = new Message();
Message message= customHander.obtainMessage();
message.arg1 = 1;
message.arg2 = 2;
message.obj = dog;
//                customHander.sendMessage(message);
message.sendToTarget();
                break;

4.訊息攔截測試

Handler interceptHander = new Handler(new Handler.Callback() {
    @Override
public boolean handleMessage(Message msg) {
        Toast.makeText(HandlerDemoActivity.this, "callback handleMessage", Toast.LENGTH_SHORT).show();
System.out.println("is intercept Handler>"+msg.what);
// 設定true攔截訊息
return true;
}
}){
    @Override
public void handleMessage(Message msg) {
        System.out.println("is intercept Handler");
}
};
點選事件
case R.id.id_btn6:
    interceptHander.sendEmptyMessage(1);
    break;
5.子執行緒中例項化hangler崩潰測試
  case R.id.id_btn7:
                new Thread() {
                    @Override
public void run() {
                        try {
                            Thread.sleep(1000*3);
//                    idTv.setText("UI執行緒更新UI會出現什麼異常呢?");
new Handler().post(new Runnable() {
                                @Override
public void run() {
                                    idTv.setText("又蹦啦");
}
                            });
} catch (InterruptedException e) {
                            e.printStackTrace();
}
                    }
                }.start();
                break;
6.自定義一個與執行緒相關Handler
public class HandlerActivity extends AppCompatActivity {
    private MyThread myThread;
    private Handler handler = new Handler(){
        @Override
public void handleMessage(Message msg) {
            System.out.println("UI ==:"+ Thread.currentThread());
}
    };
    class MyThread extends Thread {
        public Handler handler;
@Override
public void run() {
            Looper.prepare();
handler= new Handler(){
                @Override
public void handleMessage(Message msg) {
                    System.out.println("currentThread:=="+ Thread.currentThread());
}
            };
Looper.loop();
}
    }

    @Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
myThread = new MyThread();
myThread.start();
        try {
            Thread.sleep(1000*5);
} catch (InterruptedException e) {
            e.printStackTrace();
}
        myThread.handler.sendEmptyMessage(1);
handler.sendEmptyMessage(1);
}
}
效果列印:

06-29 17:07:30.519 9652-11848/com.example.jinboy.codertodeveloperbytcler I/System.out: currentThread:==Thread[Thread-9681,5,main]
06-29 17:07:30.659 9652-9652/com.example.jinboy.codertodeveloperbytcler I/System.out: UI ==:Thread[main,5,main]

7.Handler非同步訊息處理

public class HandlerThreadActivity extends AppCompatActivity implements View.OnClickListener {
    private Button idBtn1,idBtn2;
    private Handler threadhandler;
    private HandlerThread thread;
Handler handler = new Handler() {
        @Override
public void handleMessage(Message msg) {
            System.out.println("UI thread==>" + Thread.currentThread());
// 給主執行緒傳送訊息
Message message = new Message();
message.what =1;
threadhandler.sendMessageDelayed(message, 1000);
}
    };
@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_thread);
idBtn1 = (Button) findViewById(R.id.id_btn1);
idBtn2 = (Button) findViewById(R.id.id_btn2);
idBtn1.setOnClickListener(this);
idBtn2.setOnClickListener(this);
thread = new HandlerThread("Handler Thread");
thread.start();
threadhandler = new Handler(thread.getLooper()) {
            @Override
public void handleMessage(Message msg) {
                // 處理耗時操作
System.out.println("current thread==>" + Thread.currentThread());
// 給主執行緒傳送訊息
Message message = new Message();
message.what =1;
handler.sendMessageDelayed(message, 1000);
}
        };
//        threadhandler.sendEmptyMessage(1);
}

    @Override
public void onClick(View view) {
        switch (view.getId()) {
            case R.id.id_btn1:
                handler.sendEmptyMessage(1);
                break;
            case R.id.id_btn2:
                handler.removeMessages(1);
threadhandler.removeMessages(1);
                break;
}
    }
}
列印輸出


五丶參考連結和拓展學習

參考內容:

拓展學習:

六丶日常開發案例

1.Android避免在主執行緒進行網路請求和UI操作

方法一:執行緒請求網路+Handler更新UI

//handler 處理返回的請求結果
handler = new Handler() {
    @Override
public void handleMessage(Message msg) {
        super.handleMessage(msg);
Bundle data = msg.getData();
String val = data.getString("value");
tv_name.setText(tvName);
tv_originalArticleNumber.setText(tvOriginalArticleNumber);
tv_visitNumber.setText(tvVisitNumber);
tv_mark.setText(tvMark);
tv_rank.setText(tvRank);
Log.i("mylog", "請求結果-->" + val);
}
};
//新執行緒進行網路請求
Runnable runnable = new Runnable() {
    @Override
public void run() {
        BlogAuthor blogAuthor = JsoupUtil.getBlogAutoMessage();
tvName = blogAuthor.getAuthorName() + "\n" + blogAuthor.getCode()
                + "\n" + blogAuthor.getMyHelloWorld();
tvOriginalArticleNumber = blogAuthor.getOriginalArticleNumber();
tvVisitNumber = blogAuthor.getVisitNumber();
tvMark = blogAuthor.getMark();
tvRank = blogAuthor.getRank();
Message msg = new Message();
Bundle data = new Bundle();
data.putString("value", "請求結果");
msg.setData(data);
handler.sendMessage(msg);
}
};
new Thread(runnable).start();  //啟動子執行緒
方法二:強制在UI執行緒更新UI請求網路
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}

相關推薦

Android通訊模組執行執行通訊方式Handler UI Thread互動Handler接合執行的使用

一丶概述 本週的學習計劃是Android通訊模組,內容:單執行緒,多執行緒通訊方式,Handler 與UI Thread的互動,Handler接合子執行緒的使用。 二丶效果演示(原始碼連結見文末) 三丶實現功能 1.演示使用Handler常見崩潰 2.handler更新

計算機網路的三種通訊模式廣播組播小結

1.單播(Unicast) 單播在傳送者和每一接收者之間實現點對點網路連線。 如果一臺傳送者同時給多個的接收者傳輸相同 的資料,也必須相應的複製多份的相同資料包。如果有大量主機希望獲得資料包的同一份拷貝時, 將 導致傳送者負擔沉重、延遲長、網路擁塞;為保證一定

Android 手勢識別擊 雙擊 擡起 短按 長按 滾動 滑動

對於觸控式螢幕,其原生的訊息無非按下、擡起、移動這幾種,我們只需要簡單過載onTouch或者設定觸控偵聽器setOnTouchListener即可進行處理。不過,為了提高我們的APP的使用者體驗,有時候我們需要識別使用者的手勢,Android給我們提供的手勢識別工具Ge

計算機網路三種通訊模式播、廣播、組播小結

1、單播定義:單播在傳送者和每一接收者之間實現點對點網路連線。如果一臺傳送者同時給多個接收者傳輸相同的資料,也必須相應的複製多份的相同資料包。如果有大量主機希望獲得資料包的同一份拷貝時,將導致傳送者負擔沉重、延遲長、網路擁塞,為保證一定的服務質量需增加硬體和頻寬。單播優點:1

Socket 服務端使用執行實現客戶端通訊例項

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; impo

socket使用執行實現客戶端通訊

伺服器端:package com.imooc;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;/* * 基於TCP協議的Socket通訊,實現使用者登入 * 伺服器端

OGG進程拆分表拆成個進程

byte utf 主機 al32utf8 spa pup epo 同時 edi OGG進程拆分(單表拆成多個進程) 概要: 《OGG進程拆分》介紹了如何將一個入庫進程中的多個表拆分到其他進程中。本篇將著重介紹如何使用多個進程同時入庫一張表。 適用條件: 1)入庫進程只同

python文件封裝成*.exe文件文件和文件

-- 黑板 workday 程序包 代碼 拷貝 4.5 hole nic 環境:win10 64位 python3.7 單*.py文件打包Python GUI:程序打包為exe 一、安裝Pyinstaller,命令pip install Pyinstaller,(大

基於註解的Hibernate JPA操作CRUD表、一對

0.maven引入相關依賴資源 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/200

SpringBoot進階之檔案上傳檔案上傳/檔案上傳

1.單檔案上傳 private String uploadPath="D:\\tomcat\\apache-tomcat-7.0.81-windows-x64\\apache-tomcat-7

給定一個數組按序排列從陣列找出若干個數使得這若干個數字的和M最為接近揹包問題

思路:對於陣列中的每一個數,觀察它們取或不取對最後結果的影響。並且記錄下若干數字的和與M的差的絕對值最小時所取到的若干數字。 /*  * 微軟100, 9月28題, 輸入和接近M  * sum 即為M值  * num排序的陣列  * len陣列長度  * vec所取到若干數

Retrofit2快速入門使用及檔案上傳上傳、上傳

前言 在開發專案中經常會遇到上傳頭像的問題,那我們如果使用Retrofit做網路請求時,如何進行使用,在文章的最後有最清晰的使用方法 Retrofit可以認為是Okhttp的 “升級版”,為什麼這麼說?那是因為其內部預設是基於OkHttp來進行

Android實現登入功能Android伺服器資料互動使用tomcat、mysql實現登入的demo程式web端和android均可實現登入

1.使用到的開發工具為:Eclipse(Java EE),Android Studio,MYSQL 5.7.21;2.首先在MYSQL資料庫建表,我這裡使用的資料庫視覺化操作軟體為:navicat premium:如圖:這裡你可以取自己喜歡的資料庫名字,但是為了方便起見,我建

java檔案下載功能程式碼檔案下載、檔案批量打包下載——普遍適用

一、前言   程式設計師在做web等專案的時候,往往都需要新增檔案上傳、下載、刪除的功能,有時是單檔案,有時多檔案批量 操作,而這些功能的程式碼程式設計師可以自己收藏起來當成工具使用,這樣,程式設計師在進行程式設計的時候就會事半功倍 了,那麼接下來的部落格

FLEXJS資料互動以及Google外掛IFrame的使用

       最近因為專案需要,用到的flex,同時需要與js做資料互動,同時還用到了Google的外掛IFrame,總結一點點自己的使用心得,其中很多資料都是在網上Google到的。     FLEX呼叫

findViewById 的偷懶方案這函式名哈哈。除了註解和線上生成了種偷懶方式

在微博中發現的偷懶方案,好簡單。。 //結果與(...)findViewById(R.id....)一模一樣,採用$作為方法名稱,借鑑自jQuery public <T extends Vie

如何實現Echart不刷新頁面語言切換下的地圖數據重新加載api請求數據加載soketed數據實時加載

oca class 頁面 har lse setoption bsp div 監聽 可視化項目中經常用到ecahrt,各種異步加載,連接socket,多語言切換等問題,現在匯總一下: Ecahrt初始化,全局統一init,可以初始化為0,等待後續數據操作 1、如果是ap

iOS網頁JS互動看我就夠了

隨著移動APP的快速迭代開發趨勢,越來越多的APP中嵌入了html網頁,但在一些大中型APP中,尤其是電商類APP,html頁面已經不僅僅滿足展示功能,這時html要求能與原生語言進行互動、相互傳值。比如攜程APP中一個熱門景點的網頁中,點選某個景點,

Java——執行基本使用 餓漢式和懶漢式的例設計模式執行之間的通訊

這一則部落格主要寫的是單例設計模式,與實現多執行緒之間的通訊等等~ 1.單例設計模式:保證類在記憶體中只有一個物件 2.保證類在記憶體中只有一個物件            &

Android連線伺服器從伺服器獲取資料以及從伺服器下載檔案執行

首先需要在Eclipse中建立一個伺服器,在其中存入要下載的檔案,具體可參考之前的伺服器篇。 ScollView可以上下滑動 另外還有,android中的網路連線與之前java中可以通用,可以參照之前伺服器客戶端通訊篇。 新增的許可權