最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android中handler使用淺析

 更新時(shí)間:2017年03月03日 10:57:23   作者:潘侯爺  
本文主要介紹了Android中handler的使用,具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧

1. Handler使用引出

現(xiàn)在作為客戶,有這樣一個(gè)需求,當(dāng)打開Activity界面時(shí),開始倒計(jì)時(shí),倒計(jì)時(shí)結(jié)束后跳轉(zhuǎn)新的界面(思維活躍的朋友可能立馬想到如果打開后自動(dòng)倒計(jì)時(shí),就類似于各個(gè)APP的歡迎閃屏頁(yè)面),如下圖:

作為初學(xué)者,可能覺得直接開啟一個(gè)包含倒序循環(huán)的子線程就ok了,具體實(shí)現(xiàn)如下:

1.1 Layout界面代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/activity_main2"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical"
tools:context="com.mly.panhouye.handlerdemo.Main2Activity">
 <TextView
 android:gravity="center"
 android:textSize="30sp"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:text="NO DATA"
 android:id="@+id/tv"/>
</LinearLayout>

1.2 java實(shí)現(xiàn)代碼如下:

public class Main2Activity extends AppCompatActivity {
 TextView tv;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main2);
 tv = (TextView) findViewById(R.id.tv);
 new Thread(new Runnable() {
  @Override
  public void run() {
  for (int i=5;i>0;i--){
   tv.setText(String.valueOf(i));
   try {
   Thread.sleep(1000);
   } catch (InterruptedException e) {
   e.printStackTrace();
   }
  }
  //計(jì)時(shí)結(jié)束后跳轉(zhuǎn)到其他界面
  startActivity(new Intent(Main2Activity.this,Main3Activity.class));
  //添加finish方法在任務(wù)棧中銷毀倒計(jì)時(shí)界面,使新開界面在回退時(shí)直接退出而不是再次返回該界面
  finish();
  }
 }).start();
 }

邏輯很簡(jiǎn)單,但當(dāng)點(diǎn)進(jìn)入界面時(shí),會(huì)發(fā)現(xiàn)程序奔潰了,logcat中錯(cuò)誤日志如下(只有UI線程可以更改UI界面):

由此我們發(fā)現(xiàn)在安卓開發(fā)中,例如上面的示例,我們常常通過(guò)一個(gè)線程來(lái)完成某些操作,然后同步顯示對(duì)應(yīng)的視圖控件UI上,通過(guò)上面的例子我們也知道了安卓中無(wú)法直接通過(guò)子線程來(lái)進(jìn)行UI更新操作,對(duì)于這種情況,Android提供了一套異步消息處理機(jī)制Handler。

2. Handler實(shí)現(xiàn)方法

使用handler實(shí)現(xiàn),修改java代碼Main2Activity.java如下:

package com.mly.panhouye.handlerdemo;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
/**
 * Handler:
 * 1 處理的消息對(duì)象就是Message,理解為要傳遞的消息數(shù)據(jù)的封裝對(duì)象
 * Message what : 標(biāo)記,用來(lái)區(qū)分多個(gè)消息
 * Message arg1,arg2 : 用來(lái)傳遞int類型的數(shù)據(jù)
 * Message obj : 可以傳遞任何類型的對(duì)象(Object)
 */
public class Main2Activity extends AppCompatActivity {
 public static final int UPDATE = 0x1;
 TextView tv;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main2);
 tv = (TextView) findViewById(R.id.tv);
 begin();//開啟倒計(jì)時(shí)并跳轉(zhuǎn)頁(yè)面的方法
 }
 //消息處理者,創(chuàng)建一個(gè)Handler的子類對(duì)象,目的是重寫Handler的處理消息的方法(handleMessage())
 private Handler handler = new Handler(){
 @Override
 public void handleMessage(Message msg) {
  switch (msg.what){
  case UPDATE:
   tv.setText(String.valueOf(msg.arg1));
   break;
  }
 }
 };
 public void begin(){
 new Thread(new Runnable() {
  @Override
  public void run() {
  for (int i=5;i>0;i--){
   Message msg = new Message();
   msg.what = UPDATE;
   msg.arg1 = i;
   handler.sendMessage(msg);
   try {
   Thread.sleep(1000);//休眠1秒
   } catch (InterruptedException e) {
   e.printStackTrace();
   }
   //打印log
   Log.i("tag",Main2Activity.this+"-"+ i);
  }
  //計(jì)時(shí)結(jié)束后跳轉(zhuǎn)到其他界面
  startActivity(new Intent(Main2Activity.this,Main3Activity.class));
  //添加finish方法在任務(wù)棧中銷毀倒計(jì)時(shí)界面,使新開界面在回退時(shí)直接退出而不是再次返回該界面
  finish();
  }
 }).start();
 }
 @Override
 protected void onDestroy() {
 super.onDestroy();
 //log打印用于測(cè)試activity銷毀
 Log.i("tag","destory");
 }
}

3. Handler實(shí)現(xiàn)原理

使用Handler方式進(jìn)行異步消息處理主要由Message,Handler,MessageQueue,Looper四部分組成:

(1)Message,線程之間傳遞的消息,用于不同線程之間的數(shù)據(jù)交互。Message中的what字段用來(lái)標(biāo)記區(qū)分多個(gè)消息,arg1、arg2 字段用來(lái)傳遞int類型的數(shù)據(jù),obj可以傳遞任意類型的字段。

(2)Handler,用于發(fā)送和處理消息。其中的sendMessage()用來(lái)發(fā)送消息,handleMessage()用于消息處理,進(jìn)行相應(yīng)的UI操作。

(3)MessageQueue,消息隊(duì)列(先進(jìn)先出),用于存放Handler發(fā)送的消息,一個(gè)線程只有一個(gè)消息隊(duì)列。

(4)Looper,可以理解為消息隊(duì)列的管理者,當(dāng)發(fā)現(xiàn)MessageQueue中存在消息,Looper就會(huì)將消息傳遞到handleMessage()方法中,同樣,一個(gè)線程只有一個(gè)Looper。

Handler實(shí)現(xiàn)原理如下圖:

結(jié)合上文的的代碼示例以及上圖的實(shí)現(xiàn)流程,要使用Handler實(shí)現(xiàn)異步消息處理,首先我們需要在主線程中創(chuàng)建Handler對(duì)象并重寫handleMessage()方法,然后當(dāng)子線程中需要進(jìn)行UI操作時(shí),就創(chuàng)建一個(gè)Message對(duì)象,并通過(guò)Handlerr將這條消息發(fā)送出去。之后這條消息會(huì)被添加到MessageQueue的隊(duì)列中等待被處理,而Looper則會(huì)一直嘗試從MessageQueue中取出待處理消息,最后分發(fā)回Handler的handleMessage()方法中。由于Halldler是在主線程中創(chuàng)建的,所以此時(shí)handleMessage()方法中的代碼也會(huì)在主線程中運(yùn)行,從而實(shí)現(xiàn)子線程通過(guò)Handler機(jī)制實(shí)現(xiàn)UI線程操作的目的。

4. Handler內(nèi)存泄漏分析

4.1 Handler內(nèi)存泄漏問題的引出:

上面的Handler實(shí)現(xiàn)代碼中,其實(shí)在Android Studio中會(huì)提示以下問題:

大致意思就是應(yīng)該讓Handler類為靜態(tài)的,不然就會(huì)產(chǎn)生內(nèi)存泄漏。 原因也說(shuō)的很清楚,Handler被聲明為一個(gè)非靜態(tài)內(nèi)部類或者匿名類可能會(huì)阻止外部類的垃圾回收(大家可以了解下Android的gc回收機(jī)制)。過(guò)多的內(nèi)存泄漏使程序占用的內(nèi)存超出系統(tǒng)限制,導(dǎo)致OOM(內(nèi)存溢出),程序出錯(cuò)。

4.2 防止Handler引起內(nèi)存泄漏:

方法一:通過(guò)程序邏輯進(jìn)行保護(hù):

(1)在關(guān)閉Activity時(shí)停掉對(duì)應(yīng)的后臺(tái)線程。線程停止就相當(dāng)于切斷了Handle和外部鏈接的線,Activity自然會(huì)在合適的時(shí)候被回收。

(2)如果Handler是被delay的Message持有了引用,那就使用Handler的removeCallbacks()方法將消息對(duì)象從消息隊(duì)列移除即可。

方法二:將Handler聲明為靜態(tài)類,靜態(tài)類不持有外部類的對(duì)象,所以Activity可以被隨意回收。此處使用了弱引用WeakReference,也就是說(shuō)當(dāng)在內(nèi)存不足時(shí),系統(tǒng)會(huì)銷毀弱/回收引用引用的對(duì)象,從而達(dá)到優(yōu)化內(nèi)存的目的。優(yōu)化后代碼如下:

package com.mly.panhouye.handlerdemo;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.TextView;
import java.lang.ref.WeakReference;
public class Main4Activity extends AppCompatActivity {
 public static final int UPDATE = 0x1;
 TextView tv;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main2);
 tv = (TextView) findViewById(R.id.tv);
 begin();//開啟倒計(jì)時(shí)并跳轉(zhuǎn)頁(yè)面的方法
 }
 //Handler靜態(tài)內(nèi)部類
 private static class MyHandler extends Handler {
 //弱引用
 WeakReference<Main4Activity> weakReference;
 public MyHandler(Main4Activity activity) {
  weakReference = new WeakReference<Main4Activity>(activity);
 }
 @Override
 public void handleMessage(Message msg) {
  Main4Activity activity = weakReference.get();
  if (activity != null) {
  activity.tv.setText(String.valueOf(msg.arg1));
  }
 }
 }
 private MyHandler handler = new MyHandler(this);
 public void begin() {
 new Thread(new Runnable() {
  @Override
  public void run() {
   for (int i = 5; i > 0; i--) {
   Message msg = new Message();
   msg.what = UPDATE;
   msg.arg1 = i;
   handler.sendMessage(msg);
   try {
    Thread.sleep(1000);//休眠1秒
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   Log.i("tag", Main4Activity.this + "-" + i);
   }
   //計(jì)時(shí)結(jié)束后跳轉(zhuǎn)到其他界面
   startActivity(new Intent(Main4Activity.this, Main3Activity.class));
   //添加finish方法在任務(wù)棧中銷毀倒計(jì)時(shí)界面,使新開界面在回退時(shí)直接退出而不是再次返回該界面
   finish();
  }
 }).start();
 }
 @Override
 protected void onDestroy() {
 super.onDestroy();
 handler.removeCallbacksAndMessages(null);
 Log.i("tag", "destory");
 }
}

5.小結(jié)

本次使用handler實(shí)現(xiàn)倒計(jì)時(shí)頁(yè)面跳轉(zhuǎn)的效果實(shí)現(xiàn),只是向大家簡(jiǎn)單介紹handler的使用方法以及注意事項(xiàng),但依然存在bug,如果倒計(jì)時(shí)未完成時(shí)退出activity,子線程依然會(huì)在后臺(tái)運(yùn)行直至完成跳轉(zhuǎn),效果以及l(fā)og日志如下:

針對(duì)這種情況,我處理起來(lái)比較麻煩,需要在銷毀倒計(jì)時(shí)activity時(shí),同時(shí)終止線程,我試了很多方法,未能實(shí)現(xiàn)。

其實(shí)要實(shí)現(xiàn)倒計(jì)時(shí)閃屏效果,可以使用Android中有個(gè)countDownTimer類來(lái)實(shí)現(xiàn),后面會(huì)做簡(jiǎn)單的實(shí)現(xiàn)介紹。

以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!

相關(guān)文章

  • Android Material Design 陰影實(shí)現(xiàn)示例

    Android Material Design 陰影實(shí)現(xiàn)示例

    這篇文章主要介紹了Android Material Design 陰影實(shí)現(xiàn)示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-04-04
  • Android實(shí)現(xiàn)消水果游戲代碼分享

    Android實(shí)現(xiàn)消水果游戲代碼分享

    本文給大家分享實(shí)現(xiàn)開心消水果游戲的核心代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友一起看看吧
    2016-11-11
  • Android開發(fā)之簡(jiǎn)單文件管理器實(shí)現(xiàn)方法

    Android開發(fā)之簡(jiǎn)單文件管理器實(shí)現(xiàn)方法

    這篇文章主要介紹了Android開發(fā)之簡(jiǎn)單文件管理器實(shí)現(xiàn)方法,簡(jiǎn)單實(shí)現(xiàn)了Android的文件目錄查看,文件重命名,打開,刪除等功能,需要的朋友可以參考下
    2016-01-01
  • Android Studio SVN使用方法教程

    Android Studio SVN使用方法教程

    這篇文章主要介紹了Android Studio SVN使用方法教程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Android OnFocuChangeListener焦點(diǎn)事件詳解

    Android OnFocuChangeListener焦點(diǎn)事件詳解

    這篇文章主要為大家詳細(xì)介紹了Android OnFocuChangeListener焦點(diǎn)事件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • Android自定義圓角ImageView控件

    Android自定義圓角ImageView控件

    這篇文章主要為大家詳細(xì)介紹了Android自定義圓角ImageView的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Android  調(diào)用系統(tǒng)應(yīng)用的方法總結(jié)

    Android 調(diào)用系統(tǒng)應(yīng)用的方法總結(jié)

    這篇文章主要介紹了Android 調(diào)用系統(tǒng)應(yīng)用的方法總結(jié)的相關(guān)資料,這里提供調(diào)用錄像,錄音,拍照等功能,需要的朋友可以參考下
    2017-08-08
  • Android仿ViVO X6 極速閃充動(dòng)畫效果

    Android仿ViVO X6 極速閃充動(dòng)畫效果

    這篇文章主要介紹了Android仿ViVO X6 極速閃充動(dòng)畫效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • Android 三種延遲操作的實(shí)現(xiàn)方法

    Android 三種延遲操作的實(shí)現(xiàn)方法

    這篇文章主要介紹了Android 延遲操作的實(shí)現(xiàn)方法的相關(guān)資料,這里提供了三種實(shí)現(xiàn)方法,希望能幫助到大家,需要的朋友可以參考下
    2017-08-08
  • 讓IjkPlayer支持插入自定義的GPU濾鏡方法

    讓IjkPlayer支持插入自定義的GPU濾鏡方法

    下面小編就為大家分享一篇讓IjkPlayer支持插入自定義的GPU濾鏡方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01

最新評(píng)論

江阴市| 广西| 章丘市| 房山区| 宝丰县| 夹江县| 五峰| 阜新市| 凤阳县| 玉溪市| 泸水县| 伊通| 航空| 平定县| 塔城市| 仪征市| 哈尔滨市| 大丰市| 屯留县| 凯里市| 罗城| 长武县| 岑溪市| 延安市| 名山县| 得荣县| 池州市| 左云县| 兴文县| 如东县| 甘谷县| 临夏县| 崇信县| 彭泽县| 彭阳县| 庐江县| 莫力| 衡东县| 河西区| 惠州市| 涞水县|