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();以上基本是在整理文章前關於handler的所有運用。//★4.記得關閉重新整理,否則重新整理球一直在轉 mSwipeRefreshLayout.setRefreshing(false); } }, 50); }
好了,現在重新認識
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等專案的時候,往往都需要新增檔案上傳、下載、刪除的功能,有時是單檔案,有時多檔案批量 操作,而這些功能的程式碼程式設計師可以自己收藏起來當成工具使用,這樣,程式設計師在進行程式設計的時候就會事半功倍 了,那麼接下來的部落格
FLEX與JS資料互動,以及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中可以通用,可以參照之前伺服器客戶端通訊篇。 新增的許可權