Android学习笔记9---Handler
来源:互联网 发布:尚硅谷java视频教程 编辑:程序博客网 时间:2024/06/07 00:38
what is handler?
因为android的UI操作不是线程安全的,只有主线程才能对UI进行操作,如果我们想对UI进行操作,那么就需要用到handler消息处理机制
消息处理机制的步骤:
Step1.在Activity中创建Handler
Step2.在子线程中用handler发消息
Step3.在handlerMessage方法中处理消息
以下内容参见《Android》从入门到精通 清华大学出版社(明日科技编著)
通过Thread类构造方法创建线程
MainActivity.java:
Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(1500); Intent intent = new Intent(MainActivity.this,Main2Activity.class); startActivity(intent); } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start();
使用线程做一个播放背景音乐小demo
package amy.com.playbgsound;import android.media.MediaPlayer;import android.renderscript.RenderScript;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity { private Thread thread; private static MediaPlayer mp = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button1); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //设置按钮不可用 ((Button)v).setEnabled(false); thread = new Thread(new Runnable(){ @Override public void run() { playBGSound(); } }); thread.start(); } }); } private void playBGSound(){ if(mp!=null) {//释放资源 mp.release(); } mp = MediaPlayer.create(MainActivity.this,R.raw.cd); mp.start(); //位MediaPlayer添加播放完成事件监听器 mp.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { try { Thread.sleep(1500); playBGSound(); }catch (InterruptedException e) { e.printStackTrace(); } } }); } @Override protected void onDestroy() { if(mp!=null) { mp.stop(); mp.release(); mp = null; } if(thread!=null) { thread = null; } super.onDestroy(); }}
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="amy.com.playbgsound.MainActivity"> <FrameLayout android:layout_width="wrap_content" android:layout_height="wrap_content"> <Button android:id="@+id/button1" android:layout_width="400dp" android:layout_height="fill_parent" android:text="点我播放背景音乐" android:textSize="40dp" android:textColor="#ffffff" android:background="#000000" tools:layout_editor_absoluteY="8dp" tools:layout_editor_absoluteX="8dp" /> </FrameLayout></android.support.constraint.ConstraintLayout>
Handler消息传递机制
循环者Looper简介
下图是Thread-Looper-MessageQueue三者之间的关系
Looper对象是用来为线程开一个消息循环的,从而操作MessageQueue,默认情况下,Android中创建的线程是没有开消息循环的,except for main Thread.系统会自动为主线程创建Looper对象,开启消息循环。
在主线程中:Handler handler = new Handler();是不会有错的,But在非主线程中就又bug了。
使用非主线程创建一个Handler对象
LooperThread.java
package amy.com.handlertest;import android.os.Handler;import android.os.Looper;import android.os.Message;import android.util.Log;/** * Created by Administrator on 2017/9/23/023. */public class LooperThread extends Thread { public Handler handler1; @Override public void run() { super.run(); //初始化Looper Looper.prepare(); //实例化一个Handler对象 handler1 = new Handler() { public void handleMessage(Message msg) { Log.e("Looper","1111111111111111111"); } }; Message m = handler1.obtainMessage();//获取一个消息 handler1.sendMessage(m); Looper.loop(); }}MainActivity.java
在onCreate方法里面加入如下两行代码
LooperThread thread = new LooperThread(); thread.start();运行效果
Looper类提供的常用方法有:
PS:Looper.loop()后的代码不会被执行,loop内部循环。
只有在调用了Handler.getLooer().quit()方法后,loop方法才会终止,后面的代码才会被执行。
Handler简介
Handler,消息处理类,允许发送和处理Message或Runnable接口对象到它所在线程的MessageQueue中。Handler主要有两个作用:
作用1.
将Message或Runnbale应用post()或者sendMessage()方法发送到MessageQueue中,在发送时可以指定延迟时间,发送时间以及要携带的Bundle数据。当MessageQueue循环到该Message时,就调用相应的Handler对象的handlerMessage()方法对其进行处理
作用2.
在子线程中与主线程进行通信,也就是在工作线程中与UI线程进行通信。
PS:在一个线程中,只能有一个Looper和MessageQueue,但是有多个Handler,而且这些Handler可以共享同一个Looper和MessageQueue
Handler类提供的常用方法
消息类Message
省略n段描述。。。。
获取网络图片显示到ImageView中小demo
MainActivity.java:
package com.amy.handlertest2;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.widget.ImageView;import java.io.IOException;import java.io.InputStream;import java.net.URL;import java.net.URLConnection;public class MainActivity extends AppCompatActivity { private ImageView iv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv = (ImageView) findViewById(R.id.imageView1); new Thread(new Runnable() { Bitmap bitmap = null; @Override public void run() { //从网络中获取图片 //bitmap = getPicture("http://localhost:8088/MUKE.jpg");写这个地址是访问不到的 bitmap = getPicture("http://10.150.16.216:8088/MUKE.jpg"); Log.e("bitmap",bitmap.toString()); try { Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } //发送一个Runnable对象 iv.post(new Runnable() { @Override public void run() { iv.setImageBitmap(bitmap); } }); } }).start();// thread.start(); } /** * 功能:根据网址获取图片对应的Bitmap对象 * */ public Bitmap getPicture(String path) { Bitmap bm = null; try { //创建URL对象 URL url = new URL(path); //获取URL对象对应的链接 URLConnection conn = url.openConnection(); //打开链接 conn.connect(); //获取输入流对象 InputStream is= conn.getInputStream(); //根据输入流对象创建对应的Bitmap bm = BitmapFactory.decodeStream(is); } catch (IOException e) { e.printStackTrace(); } return bm; }}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.amy.handlertest2.MainActivity"> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/pic" /></android.support.constraint.ConstraintLayout>
在AndroidManifest.xml中加入网络访问权限:
<uses-permission android:name="android.permission.INTERNET"/>效果图。1.5s后界面显示网络访问的图片
后续再补充。。。。。
再来一个小demo---多彩霓虹灯
MainActivity.java
package com.amy.color;import android.content.res.Resources;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.ViewGroup;import android.view.WindowManager;import android.widget.LinearLayout;import android.widget.TextView;import java.util.Random;public class MainActivity extends AppCompatActivity { private Handler handler; private static LinearLayout linearLayout; public static TextView[] tv = new TextView[14]; int[] bgClor = new int[]{R.color.color1,R.color.color2, R.color.color3,R.color.color4, R.color.color5,R.color.color6,R.color.color7}; private int index = 0;//当前颜色的值 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);// getSupportActionBar().hide();// //就可以隐藏标题,全屏显示// // 隐藏状态栏// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,// WindowManager.LayoutParams.FLAG_FULLSCREEN); linearLayout = (LinearLayout) findViewById(R.id.ll); int height = this.getResources().getDisplayMetrics().heightPixels;//获取屏幕高度 for (int i=0;i<tv.length;i++) { tv[i] = new TextView(this); tv[i].setWidth(this.getResources().getDisplayMetrics().widthPixels);//设置文本框的宽度 tv[i].setHeight(height/tv.length); linearLayout.addView(tv[i]);// tv[i].setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,50));// linearLayout.addView(tv[i]); } //创建一个线程实现循环 Thread thread = new Thread(new Runnable() { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { Message m = handler.obtainMessage(); m.what = 0x101; handler.sendMessage(m); try { Thread.sleep(new Random().nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } } } }); thread.start(); //创建一个Handler对象,在重写的handlerMessage()方法中,为每个文本框设置背景颜色 handler = new Handler() { @Override public void handleMessage(Message msg) { int temp; if(msg.what == 0x101) { for (int i=0;i<tv.length;i++) { temp = new Random().nextInt(bgClor.length);//产生一个随机数 //去掉重复色 if(index == temp) { temp++; if(temp == bgClor.length) { temp =0; } } index = temp; //为文本框设置背景 tv[i].setBackgroundColor(getResources().getColor(bgClor[index]));// Log.e(tv[i].getBackground()); } } super.handleMessage(msg); } }; }}activity_main.xml
<?xml version="1.0" encoding="utf-8"?><android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.amy.color.MainActivity"> <LinearLayout android:id="@+id/ll" android:orientation="vertical" android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </LinearLayout></android.support.constraint.ConstraintLayout>
values/color.xml:
<?xml version="1.0" encoding="utf-8"?><resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="color1">#ffff0000</color> <color name="color2">#ffff6600</color> <color name="color3">#ffffff00</color> <color name="color4">#ff00ff00</color> <color name="color5">#ff00ffff</color> <color name="color6">#ff0000ff</color> <color name="color7">#ff6600ff</color></resources>效果图:
调试期间遇到的问题,布局的设置有问题,
刚开始在LinearLayout中的布局是这样写的:
<LinearLayout android:id="@+id/ll" android:layout_width="wrap_content" android:layout_height="wrap_content">所以,属性还是没有掌握扎实,所以导致运行出来是这个样子:
经过反复调整才出现多彩现象,想想自己也是够笨的。功夫没有用到位。。。。
Handler在这块起到了获取消息和处理消息的作用。至于怎么处理的,上面注释已经写的很清楚了,以后,针对需求不同酌情更改。
先学到这儿吧,后续有新内容,再添加。。。。
- Android学习笔记9---Handler
- Android Handler学习笔记
- android handler学习笔记
- Android Handler学习笔记
- Android学习笔记----Handler
- android Handler 学习笔记
- android Handler学习笔记
- android学习笔记2-handler
- android学习笔记之Handler
- Android学习笔记14:Handler
- 学习笔记---Android Handler机制
- Android学习笔记之Handler
- android Handler机制学习笔记
- Android学习笔记9——Handler初步
- Android开发学习笔记-7 Handler基础
- Android学习笔记之Handler(一)
- Android学习笔记——Handler
- android Handler 机制研究学习笔记
- GKQuadtree
- JSTL格式化日期
- PDF任务该怎样在ABBYY FineReader 中定义
- 第四周项目三 单链表应用
- WIFI模块ESP8266的使用指南(客户端和服务器两种模式建立)
- Android学习笔记9---Handler
- UVa-11292 Dragon of Loowater (贪心)
- 前端框架vue.js系列(1):基础及语法
- DPDK多线程初步解析
- 数据库——关于Oracle中[ ]通配符的使用
- DLT645-2007 规约 电表 报文解析
- [Leetcode] 405. Convert a Number to Hexadecimal 解题报告
- 保存成功后局部刷新
- JAVA试题:输出字符串中连续两个相同子串