android UI多线程
Android 多线程和异步处理
Android 多线程和异步处理Android操作系统是基于Linux内核的,而Linux内核天生支持多线程的能力。
在Android开发中,多线程和异步处理是必不可少的技术。
本文将介绍Android多线程和异步处理的相关知识。
一、多线程概述多线程是指在一个进程中同时执行多个线程,每个线程都是独立运行的,可以完整的拥有自己的资源和运行环境。
在Android应用中,多线程的使用可以提高程序的性能和用户体验。
1.1 多线程的优点通过使用多线程,可以将一些耗时的操作和主线程分开,提高程序的响应速度。
同时,多线程还可以充分利用多核处理器的计算能力,提高程序的运行效率。
1.2 多线程的分析与设计在使用多线程时,需要充分考虑线程安全性和资源的合理分配。
可以使用线程池来管理和控制线程的创建和销毁,使得线程的创建和销毁过程更加高效。
二、Android多线程实现方式Android中提供了多种多线程的实现方式,下面将介绍几种常见的实现方式。
2.1 继承Thread类继承Thread类是一种常见的实现多线程的方式。
通过继承Thread 类并重写run方法,可以实现自定义的线程功能。
```javapublic class MyThread extends Thread{@Overridepublic void run(){// 线程执行的代码}}```2.2 实现Runnable接口实现Runnable接口是另一种实现多线程的方式。
通过实现Runnable接口并实现run方法,也可以实现自定义的线程功能。
```javapublic class MyRunnable implements Runnable{@Overridepublic void run(){// 线程执行的代码}```2.3 使用Handler实现多线程在Android开发中,我们经常需要在子线程中更新UI界面。
这时可以使用Handler来实现多线程和UI更新的交互。
android 多线程面试题
android 多线程面试题Android多线程面试题Android多线程是一个重要的技术,对于开发者来说,掌握多线程编程是非常必要的。
在Android面试中,经常会出现与多线程相关的问题。
下面将介绍一些常见的Android多线程面试题,希望能够帮助你在面试中更好地回答问题。
1. 什么是多线程?多线程是指在一个进程中同时执行多个任务的技术。
在Android中,多线程可以实现在后台同时进行多个任务,以提升用户体验和应用性能。
2. 在Android中有哪些实现多线程的方式?在Android中,有以下几种实现多线程的方式:a. 使用Thread类:可以通过继承Thread类或者创建Thread匿名内部类的方式来创建线程对象,重写run()方法来定义线程执行的操作。
b. 使用Runnable接口:通过创建一个实现Runnable接口的类的实例,将其作为参数传递给Thread类的构造函数来创建线程。
c. 使用HandlerThread类:HandlerThread是继承自Thread的一个类,它内部封装了一个Looper和Handler,可以方便地实现线程间的通信。
d. 使用AsyncTask类:AsyncTask是一个封装了异步操作的类,它可以在后台执行耗时操作,并在主线程更新UI。
3. 什么是主线程和子线程?主线程是指应用程序的主要执行线程,也称为UI线程。
它负责处理用户交互、更新UI等操作。
子线程是在主线程之外创建的线程,用于执行一些耗时的操作,以保证主线程不会被阻塞。
4. 如何在子线程中更新UI?在Android中,UI更新必须在主线程中进行,但有时需要在子线程中执行一些耗时操作。
可以通过以下几种方式在子线程中更新UI:a. 使用Handler:可以在子线程中通过Handler发送消息给主线程,然后在主线程中通过Handler处理消息,更新UI。
b. 使用runOnUiThread()方法:可以在子线程中通过Activity的runOnUiThread()方法来直接更新UI。
全面详解Android实现多线程的几种方式(史上最全最详细)
全面详解Android实现多线程的几种方式(史上最全最详细)Android是一个基于Linux内核的开源操作系统,为移动设备提供了丰富的应用开发平台。
在开发过程中,多线程的使用是非常常见的,能够提升程序的性能和用户体验。
本文将全面详解Android实现多线程的几种方式,从线程的基本概念到具体的实现方法,让您全面了解Android多线程编程。
一、线程的基本概念在计算机科学中,线程是指程序中执行的最小单位,它是进程的一部分,可以独立运行、相互合作。
与进程不同的是,进程是操作系统分配资源的最小单位。
一个进程包含多个线程,它们共享进程的资源,可以同时执行。
Android中的线程是通过Thread类实现的。
每个线程对象都有一个run方法,它包含了线程要执行的代码。
二、实现多线程的几种方式1. 继承Thread类继承Thread类是最直接的实现多线程的方式。
具体步骤如下:(1)创建一个继承自Thread类的自定义类,重写run方法。
```public class MyThread extends Threadpublic void ru//线程要执行的代码}```(2)创建MyThread类的实例,并调用start方法启动线程。
```MyThread myThread = new MyThread(;myThread.start(;```2. 实现Runnable接口实现Runnable接口是更常用的实现多线程的方式。
具体步骤如下:(1)创建一个实现Runnable接口的自定义类,重写run方法。
```public class MyRunnable implements Runnablepublic void ru//线程要执行的代码}```(2)创建MyRunnable类的实例,并通过Thread类的构造方法传递给一个新的线程对象。
MyRunnable myRunnable = new MyRunnable(;Thread thread = new Thread(myRunnable);thread.start(;```3.使用线程池线程池是一种管理和复用线程的机制,可以减少线程创建、销毁的开销,提高性能。
android handlerthread用法
android handlerthread用法Android HandlerThread是Android开发中常用的多线程处理工具。
它能够在后台线程中执行任务,并通过Handler与UI线程进行通信。
本文将详细介绍HandlerThread的用法,以及如何使用它来实现多线程任务处理。
一、什么是HandlerThread?HandlerThread是Android中的一个类,继承自Thread,并实现了Looper接口。
它在后台线程中提供了一个消息循环机制,可以用来处理耗时的任务。
二、使用HandlerThread的步骤1. 创建HandlerThread实例首先,我们需要创建一个HandlerThread的实例,并给它一个有意义的名称。
例如,可以创建一个名为"BackgroundThread"的HandlerThread 实例:javaHandlerThread handlerThread = newHandlerThread("BackgroundThread");2. 启动HandlerThread接下来,我们需要调用HandlerThread的start方法来启动它的线程:javahandlerThread.start();3. 创建Handler然后,我们可以通过HandlerThread的getLooper方法获得一个Looper 实例,并将其用于创建一个Handler对象:javaHandler handler = new Handler(handlerThread.getLooper());通过这个Handler,我们可以在后台线程中发送和处理消息。
4. 发送消息现在我们可以在UI线程中通过Handler发送消息到后台线程中进行处理。
例如,我们可以发送一个Runnable对象到后台线程中执行:javahandler.post(new Runnable() {@Overridepublic void run() {在后台线程中执行耗时任务...}});5. 处理消息在HandlerThread的内部实现中,它会不断地从消息队列中取出消息并处理。
android studio中的多线程编程例子
android studio中的多线程编程例子在Android Studio中,多线程编程是一种常见且重要的技术,它可以帮助我们更有效地处理并发任务和提升应用的性能。
通过使用多线程,我们可以在应用中同时执行多个任务,从而提高用户体验。
下面我将为您提供一个Android Studio中的多线程编程的例子,帮助您更好地理解该概念和实现。
首先,我们需要在项目中创建一个新的Java类,用于定义我们的多线程任务。
假设我们要实现一个简单的计数器,可以在后台进行自增操作,并将结果显示在应用界面上。
```javapublic class CounterThread extends Thread {private boolean isRunning = true;private int counter = 0;private Handler handler;public CounterThread(Handler handler) {this.handler = handler;}@Overridepublic void run() {while (isRunning) {try {// 模拟自增操作counter++;// 发送消息给主线程更新UIMessage message = new Message();message.obj = "当前计数: " + counter;handler.sendMessage(message);// 使线程休眠1秒Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}public void stopThread() {isRunning = false;}}```在MainActivity中,我们需要处理UI更新的部分,以及创建和启动我们的CounterThread。
Android UI线程分析
理解UI线程——swt, Android, 和Swing的UI机理线程在做GUI的时候, 无论是SWT, AWT, Swing 还是Android, 都需要面对UI线程的问题, UI线程往往会被单独的提出来单独对待, 试着问自己,当GUI启动的时候, 后台会运行几个线程? 比如1. SWT 从Main函数启动2. Swing 从Main函数启动3. Android 界面启动常常我们被告知, 主线程, UI线程, 因此这里很多会回答, 有两个线程, 一个线程是Main, 另外一个是UI. 如果答案是这样, 这篇文章就是写给你的。
OK, 我们以SWT为例, 设计以下方案寻找答案, 第一步, 我们看能否找到两个线程:1. 从Main中启动SWT的界面, 在启动界面前, 将Main所在的线程打印出来这里设计为Shell中嵌入一个Button2. 点击Button, 运行一个耗时很长的操作, 反复修改Button的文字, 在该线程中打印该线程的名称代码是这样的:1.publicstaticvoid main(String[] args) {2.final Display display = Display.getDefault();3.final Shell shell = new Shell();4. shell.setSize(500, 375);5. shell.setText("SWT Application");6. shell.setLayout(new FillLayout());7. btn = new Button(shell, SWT.NULL);8. btn.setText("shit");9. registerAction();10. shell.open();11. yout();12.while (!shell.isDisposed()) {13.if (!display.readAndDispatch())14. display.sleep();15. }16. shell.dispose();17. display.dispose();18.}19.privatestaticvoid registerAction() {20. btn.addMouseListener(new MouseListener() {21. @Override22.publicvoid mouseDoubleClick(MouseEvent e) {23. // TODO Auto-generated method stub24. }25. @Override26.publicvoid mouseDown(MouseEvent e) {27. methodA();28. }29. @Override30.publicvoid mouseUp(MouseEvent e) {31. }32. });33.}34./**35.* 持续的跑动, 打印线程的名称, 注意拖拽不动, 界面死掉, 直到跑完36.*/37.privatestaticvoid methodA() {38.for (int i = 0; i < count; i++) {39. haveArest(300);40. System.out.println("MethodA:" +Thread.currentThread().getName());41. btn.setText(i + "");42. }43.}haveArest方法在最后出现, 只是封装了一个让线程等待一段时间, 打印的结果都为main, 于是得到第一个重要的结论:UI所在的线程和Main所在的线程都是同一个线程。
android线程间通信的几种方法
android线程间通信的几种方法
在Android开发中,线程间通信是一项重要的技术,通常用于在不同的线程间传递数据或通知。
下面介绍几种实现线程间通信的方法: 1. Handler
Handler是Android中最常用的线程间通信机制之一,它允许在不同线程间发送和处理消息。
在UI线程中创建一个Handler对象,
然后可以使用它来向其他线程发送消息或将消息传递回UI线程进行
处理。
2. BroadcastReceiver
BroadcastReceiver是一种广播机制,可以在应用程序内部和应用程序之间传递消息。
通过注册和发送广播,不同的线程可以相互通信,从而达到线程间通信的目的。
3. Messenger
Messenger是一种轻量级的IPC(进程间通信)机制,它允许不
同的线程使用Message对象进行通信。
Messenger通过IPC方式传递消息,可以实现跨进程的线程间通信。
4. ContentProvider
ContentProvider是一种用于访问和共享数据的机制,它可以将不同线程之间的数据进行共享。
通过ContentProvider,线程可以在不同的进程中读取和写入数据,从而达到线程间通信的目的。
总之,在Android开发中,线程间通信是非常重要的,我们需要根据具体的需求选择不同的方法来实现线程间的数据传递和通信。
以
上介绍的几种方法都是非常常用的线程间通信机制,开发者需要根据具体的情况选择最适合的方法来完成线程间的通信。
android中线程池用法
在Android中,可以使用线程池来管理线程,提高应用程序的响应性能。
以下是一些在Android中常见的线程池及其用法:1. **FixedThreadPool**:* 创建一个固定数量的线程池,当线程池中的线程都被占用时,新提交的任务会被阻塞直到有线程可用。
* 示例:```java`ExecutorService executorService = Executors.newFixedThreadPool(10);executorService.submit(() -> {// 任务代码});````2. **CachedThreadPool**:* 创建一个可缓存的线程池,当线程池中的线程数量超过核心线程数时,多余的线程会被缓存起来,当有新任务提交时,会尝试复用这些缓存的线程。
* 示例:```java`ExecutorService executorService = Executors.newCachedThreadPool();executorService.submit(() -> {// 任务代码});````3. **SingleThreadExecutor**:* 创建一个单线程的线程池,所有任务都会在一个线程中顺序执行。
* 示例:```java`ExecutorService executorService = Executors.newSingleThreadExecutor();executorService.submit(() -> {// 任务代码});````4. **ThreadPoolExecutor**:* 创建一个自定义配置的线程池,可以设置核心线程数、最大线程数、任务队列等。
* 示例:```java`ThreadPoolExecutor executorService = new ThreadPoolExecutor(5, // 核心线程数10, // 最大线程数60L, // 空闲线程存活时间(秒)TimeUnit.SECONDS, // 时间单位new ArrayBlockingQueue<Runnable>(100), // 任务队列new ThreadPoolExecutor.CallerRunsPolicy() // 当线程池已满时,新提交的任务在调用者线程中运行);executorService.submit(() -> {// 任务代码});````5. **ScheduledThreadPoolExecutor**:* 创建一个可调度的线程池,可以定时执行或周期性地执行任务。
Android的线程使用来更新UI----Thread、Handler、Looper、TimerTask等
方法一:(java习惯,在android不推荐使用)刚刚开始接触android线程编程的时候,习惯好像java一样,试图用下面的代码解决问题new Thread( new Runnable() {public void run() {myView.invalidate();}}).start();可以实现功能,刷新UI界面。
但是这样是不行的,因为它违背了单线程模型:Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。
方法二:(Thread+Handler)查阅了文档和apidemo后,发觉常用的方法是利用Handler来实现UI线程的更新的。
Handler来根据接收的消息,处理UI更新。
Thread线程发出Handler消息,通知更新UI。
Handler myHandler = new Handler() {public void handleMessage(Message msg) {switch (msg.what) {case TestHandler.GUIUPDATEIDENTIFIER:myBounceView.invalidate();break;}super.handleMessage(msg);}};class myThread implements Runnable {public void run() {while (!Thread.currentThread().isInterrupted()) {Message message = new Message();message.what = TestHandler.GUIUPDATEIDENTIFIER;TestHandler.this.myHandler.sendMessage(message);try {Thread.sleep(100);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}}以上方法demo看:/blog/411860方法三:(java习惯,不推荐)在Android平台中需要反复按周期执行方法可以使用Java上自带的TimerTask类,Tim erTask相对于Thread来说对于资源消耗的更低,除了使用Android自带的AlarmManager使用Timer定时器是一种更好的解决方法。
android多线程下载技术详解
Android 多线程、断点续传下载技术1.为什么使用该技术?答:(1)之所以采用多线程下载是因为考虑到手机,及移动设备的cup处理能力,让下载任务多抢占cup资源,从而加快了下载的速度,提高了用户体验(2)断点续传技术,就是在下载过程中如果网络出现问题,导致文件没有下载完,那么下次下载时,接着上次终端位置继续下载,从而减轻了服务器的负担。
2.下面我们就开始建一个多线程下载的项目,来体验多线程下载的优势,项目的结构如下2.1设计UImain.xml代码如下:<?xml version="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="/apk/res /android"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="@string/path"/><EditTextandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:text="/kcn/pc/K anbox_10012.exe"android:id="@+id/path"/><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="@string/button"android:id="@+id/button"/><ProgressBarandroid:layout_width="fill_parent"android:layout_height="20px"style="?android:attr/progressBarStyleHorizontal"android:id="@+id/downloadbar"/><TextViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:gravity="center"android:id="@+id/result"/></LinearLayout>其中引用的string.xml如下:<?xml version="1.0"encoding="utf-8"?><resources><string name="hello">Hello World, SmartDownload!</string><string name="app_name">SMART多线程断点下载器</string><string name="path">下载路径</string><string name="button">下载</string><string name="success">下载完成</string><string name="error">下载失败</string><string name="sdcarderror">SDCard不存在或者写保护</string></resources>3.数据库阶段:3.1编写数据库工具类DBOpenHelerpackage com.smart.db;import android.content.Context;import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper;public class DBOpenHelper extends SQLiteOpenHelper {private static final String DBNAME = "smart.db";private static final int VERSION = 1;public DBOpenHelper(Context context) {super(context, DBNAME, null, VERSION);}@Overridepublic voiddb.execSQL("CREATE TABLE IF NOT EXISTS SmartFileDownlog (id integer primary key autoincrement, downpath varchar(100), threadid INTEGER, downlength INTEGER)");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {db.execSQL("DROP TABLE IF EXISTS SmartFileDownlog");onCreate(db);}}3.2对各个线程的下载记录进行数据库的操作,编写Fileservice 类代码如下package com.smart.db;import java.util.HashMap;import java.util.Map;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase; /*** 业务bean**/public class FileService {private DBOpenHelper openHelper;public FileService(Context context) { openHelper = new DBOpenHelper(context);}/*** 获取每条线程已经下载的文件长度* @param path* @return*/public Map<Integer, Integer> getData(String path){openHelper.getReadableDatabase();Cursor cursor = db.rawQuery("select threadid, downlength from SmartFileDownlog where downpath=?", new String[]{path});Map<Integer, Integer> data = newHashMap<Integer, Integer>();while(cursor.moveToNext()){data.put(cursor.getInt(0),cursor.getInt(1));}cursor.close();db.close();return data;}/*** 保存每条线程已经下载的文件长度* @param path* @param map*/public void save(String path, Map<Integer, Integer> map){//int threadid, int positionopenHelper.getWritableDatabase();db.beginTransaction();try{for(Map.Entry<Integer, Integer> entry : map.entrySet()){db.execSQL("insert intoSmartFileDownlog(downpath, threadid, downlength) values(?,?,?)",new Object[]{path, entry.getKey(), entry.getValue()});}db.setTransactionSuccessful();}finally{db.endTransaction();}db.close();}/*** 实时更新每条线程已经下载的文件长度* @param path* @param map*/public void update(String path, Map<Integer, Integer> map){SQLiteDatabase db =openHelper.getWritableDatabase();db.beginTransaction();try{for(Map.Entry<Integer, Integer> entry : map.entrySet()){db.execSQL("update SmartFileDownlog set downlength=? where downpath=? and threadid=?",new Object[]{entry.getValue(), path, entry.getKey()});}db.setTransactionSuccessful();}finally{db.endTransaction();}db.close();}/*** 当文件下载完成后,删除对应的下载记录* @param path*/public void delete(String path){SQLiteDatabase db =openHelper.getWritableDatabase();db.execSQL("delete from SmartFileDownlog where downpath=?", new Object[]{path});db.close();}}4.实现文件下载阶段4.1建立SmartFileDownloader类用来实现文件的下载功能代码如下package com.smart.impl;import java.io.File;import java.io.RandomAccessFile;import .HttpURLConnection;import .URL;import java.util.LinkedHashMap;import java.util.Map;import java.util.UUID;import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher;import java.util.regex.Pattern;import android.content.Context;import android.util.Log;import com.smart.db.FileService;public class SmartFileDownloader {private static final String TAG = "SmartFileDownloader";private Context context;private FileService fileService;/* 已下载文件长度 */private int downloadSize = 0;/* 原始文件长度 */private int fileSize = 0;/* 线程数 */private SmartDownloadThread[] threads;/* 本地保存文件 */private File saveFile;/* 缓存各线程下载的长度*/private Map<Integer, Integer> data = new ConcurrentHashMap<Integer, Integer>();/* 每条线程下载的长度 */private int block;/* 下载路径 */private String downloadUrl;/*** 获取线程数*/public int getThreadSize() {return threads.length;}/*** 获取文件大小* @return*/public int getFileSize() {return fileSize;}* 累计已下载大小* @param size*/protected synchronized void append(int size) { downloadSize += size;}/*** 更新指定线程最后下载的位置* @param threadId 线程id* @param pos 最后下载的位置*/protected void update(int threadId, int pos) { this.data.put(threadId, pos);}/*** 保存记录文件*/protected synchronized void saveLogFile() { this.fileService.update(this.downloadUrl, this.data);}* 构建文件下载器* @param downloadUrl 下载路径* @param fileSaveDir 文件保存目录* @param threadNum 下载线程数*/public SmartFileDownloader(Context context, String downloadUrl, File fileSaveDir, int threadNum) {try {this.context = context;this.downloadUrl = downloadUrl;fileService = newFileService(this.context);URL url = new URL(this.downloadUrl);if(!fileSaveDir.exists())fileSaveDir.mkdirs();this.threads = newSmartDownloadThread[threadNum];HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setConnectTimeout(5*1000);conn.setRequestMethod("GET");conn.setRequestProperty("Accept","image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash,application/xaml+xml,application/vnd.ms-xpsdocument,application/x-ms-xbap,application/x-ms-application,application/vnd.ms-excel,application/vnd.ms-powerpoint, application/msword, */*");conn.setRequestProperty("Accept-Language", "zh-CN");conn.setRequestProperty("Referer", downloadUrl);conn.setRequestProperty("Charset","UTF-8");conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR2.0.50727; .NET CLR3.0.04506.30; .NET CLR3.0.4506.2152; .NET CLR 3.5.30729)");conn.setRequestProperty("Connection", "Keep-Alive");conn.connect();printResponseHeader(conn);if (conn.getResponseCode()==200) {this.fileSize =conn.getContentLength();//根据响应获取文件大小if (this.fileSize <= 0) throw new RuntimeException("Unkown file size ");String filename = getFileName(conn);this.saveFile = new File(fileSaveDir, filename);/* 保存文件 */Map<Integer, Integer> logdata = fileService.getData(downloadUrl);if(logdata.size()>0){for(Map.Entry<Integer, Integer> entry : logdata.entrySet())data.put(entry.getKey(),entry.getValue());}this.block = (this.fileSize %this.threads.length)==0? this.fileSize /this.threads.length : this.fileSize /this.threads.length + 1;if(this.data.size()==this.threads.length){for(int i = 0; i < this.threads.length; i++) {this.downloadSize +=this.data.get(i+1);}print("已经下载的长度"+this.downloadSize);}}else{throw new RuntimeException("server no response ");}} catch (Exception e) {print(e.toString());throw new RuntimeException("don't connection this url");}}/*** 获取文件名*/private String getFileName(HttpURLConnection conn) {String filename =this.downloadUrl.substring(stI ndexOf('/') + 1);if(filename==null ||"".equals(filename.trim())){//如果获取不到文件名称for (int i = 0;; i++) {String mine = conn.getHeaderField(i);if (mine == null) break;if("content-disposition".equals(conn.getHeader FieldKey(i).toLowerCase())){Matcher m =pile(".*filename=(.*)").matcher(mine.t oLowerCase());if(m.find()) return m.group(1);}}filename = UUID.randomUUID()+ ".tmp";//默认取一个文件名}return filename;}/*** 开始下载文件* @param listener 监听下载数量的变化,如果不需要了解实时下载的数量,可以设置为null* @return已下载文件大小* @throws Exception*/public intdownload(SmartDownloadProgressListener listener) throws Exception{try {RandomAccessFile randOut = new RandomAccessFile(this.saveFile, "rw");if(this.fileSize>0)randOut.setLength(this.fileSize);randOut.close();URL url = new URL(this.downloadUrl);if(this.data.size() !=this.threads.length){this.data.clear();//清除数据for (int i = 0; i < this.threads.length; i++) {this.data.put(i+1, 0);}}for(int i = 0; i < this.threads.length; i++) {int downLength = this.data.get(i+1);if(downLength < this.block &&this.downloadSize<this.fileSize){ //该线程未完成下载时,继续下载this.threads[i] = new SmartDownloadThread(this, url, this.saveFile, this.block, this.data.get(i+1), i+1);this.threads[i].setPriority(7);this.threads[i].start();}else{this.threads[i] = null;}}this.fileService.save(this.downloadUrl, this.data);boolean notFinish = true;//下载未完成while (notFinish) {// 循环判断是否下载完毕Thread.sleep(900);notFinish = false;//假定下载完成for (int i = 0; i < this.threads.length; i++){if (this.threads[i] != null&& !this.threads[i].isFinish()) {notFinish = true;//下载没有完成if(this.threads[i].getDownLength() == -1){//如果下载失败,再重新下载this.threads[i] = new SmartDownloadThread(this, url, this.saveFile, this.block, this.data.get(i+1), i+1);this.threads[i].setPriority(7);this.threads[i].start();}}}if(listener!=null)listener.onDownloadSize(this.downloadSize);}fileService.delete(this.downloadUrl);} catch (Exception e) {print(e.toString());throw new Exception("file download fail");}return this.downloadSize;}/*** 获取Http响应头字段* @param http* @return*/public static Map<String, String> getHttpResponseHeader(HttpURLConnection http) { Map<String, String> header = new LinkedHashMap<String, String>();for (int i = 0;; i++) {String mine = http.getHeaderField(i);if (mine == null) break;header.put(http.getHeaderFieldKey(i), mine);}return header;}/*** 打印Http头字段* @param http*/public static voidprintResponseHeader(HttpURLConnection http){ Map<String, String> header = getHttpResponseHeader(http);for(Map.Entry<String, String> entry : header.entrySet()){String key = entry.getKey()!=null ? entry.getKey()+ ":" : "";print(key+ entry.getValue());}}//打印日志private static void print(String msg){ Log.i(TAG, msg);}}4.2下载过程中的线程实现建立SmartDownloadThread类具体代码如下:package com.smart.impl;import java.io.File;import java.io.InputStream;import java.io.RandomAccessFile;import .HttpURLConnection;import .URL;import android.util.Log;public class SmartDownloadThread extends Thread { private static final String TAG = "SmartDownloadThread";private File saveFile;private URL downUrl;private int block;/* *下载开始位置 */private int threadId = -1;private int downLength;private boolean finish = false;private SmartFileDownloader downloader;public SmartDownloadThread(SmartFileDownloader downloader, URL downUrl, File saveFile, int block, int downLength, int threadId) {this.downUrl = downUrl;this.saveFile = saveFile;this.block = block;this.downloader = downloader;this.threadId = threadId;this.downLength = downLength;}@Overridepublic void run() {if(downLength < block){//未下载完成try {HttpURLConnection http = (HttpURLConnection) downUrl.openConnection();http.setConnectTimeout(5 * 1000);http.setRequestMethod("GET");http.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash,application/xaml+xml,application/vnd.ms-xpsdocument,application/x-ms-xbap,application/x-ms-application,application/vnd.ms-excel,application/vnd.ms-powerpoint, application/msword, */*");http.setRequestProperty("Accept-Language","zh-CN");http.setRequestProperty("Referer", downUrl.toString());http.setRequestProperty("Charset", "UTF-8");int startPos = block * (threadId - 1) + downLength;//开始位置int endPos = block * threadId -1;//结束位置http.setRequestProperty("Range","bytes=" + startPos + "-"+ endPos);//设置获取实体数据的范围http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR2.0.50727; .NET CLR3.0.04506.30; .NET CLR3.0.4506.2152; .NET CLR 3.5.30729)");http.setRequestProperty("Connection", "Keep-Alive");InputStream inStream =http.getInputStream();byte[] buffer = new byte[1024];int offset = 0;print("Thread "+ this.threadId+ " start download from position "+ startPos);RandomAccessFile threadfile = new RandomAccessFile(this.saveFile, "rwd");threadfile.seek(startPos);while((offset = inStream.read(buffer, 0, 1024)) != -1) {threadfile.write(buffer, 0, offset);downLength += offset;downloader.update(this.threadId, downLength);downloader.saveLogFile();downloader.append(offset);}threadfile.close();inStream.close();print("Thread " + this.threadId + " download finish");this.finish = true;} catch (Exception e) {this.downLength = -1;print("Thread "+ this.threadId+ ":"+ e);}}}private static void print(String msg){Log.i(TAG, msg);}/*** 下载是否完成* @return*/public boolean isFinish() {return finish;}/*** 已经下载的内容大小* @return如果返回值为-1,代表下载失败*/public long getDownLength() {return downLength;}}4.3 建立interface SmartDownloadProgressListener 侦听线程的下载进度代码如下:package com.smart.impl;public interface SmartDownloadProgressListener { public void onDownloadSize(int size);}5.建立activity 实现下载的触发,和界面的实时更新具体代码如下:package com.smart.activoty.download;import java.io.File;import android.app.Activity;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.ProgressBar;import android.widget.TextView;import android.widget.Toast;importcom.smart.impl.SmartDownloadProgressListener; import com.smart.impl.SmartFileDownloader;public class SmartDownloadActivity extends Activity {private ProgressBar downloadbar;private EditText pathText;private TextView resultView;private Handler handler = new Handler(){@Override//信息public void handleMessage(Message msg) { switch (msg.what) {case 1:int size = msg.getData().getInt("size");downloadbar.setProgress(size);float result =(float)downloadbar.getProgress()/(float)downloadbar.getMax();int p = (int)(result*100);resultView.setText(p+"%");if(downloadbar.getProgress()==downloadbar.getM ax())Toast.makeText(SmartDownloadActivity.this, R.string.success, 1).show();break;case -1:Toast.makeText(SmartDownloadActivity.this, R.string.error, 1).show();break;}}};@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.main);Button button =(Button)this.findViewById(R.id.button);downloadbar =(ProgressBar)this.findViewById(R.id.downloadbar); pathText =(EditText)this.findViewById(R.id.path);resultView =(TextView)this.findViewById(R.id.result);button.setOnClickListener(newView.OnClickListener() {@Overridepublic void onClick(View v) {String path =pathText.getText().toString();if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){File dir =Environment.getExternalStorageDirectory();//文件保存目录download(path, dir);}else{Toast.makeText(SmartDownloadActivity.this,R.string.sdcarderror, 1).show();}}});}//对于UI控件的更新只能由主线程(UI线程)负责,如果在非UI 线程更新UI控件,更新的结果不会反映在屏幕上,某些控件还会出错private void download(final String path, final File dir){new Thread(new Runnable() {@Overridepublic void run() {try {SmartFileDownloader loader = new SmartFileDownloader(SmartDownloadActivity.this, path, dir, 3);int length = loader.getFileSize();//获取文件的长度downloadbar.setMax(length);loader.download(new SmartDownloadProgressListener(){@Overridepublic void onDownloadSize(int size) {//可以实时得到文件下载的长度Message msg = new Message();msg.what = 1;msg.getData().putInt("size", size);handler.sendMessage(msg);}});} catch (Exception e) {Message msg = new Message();//信息提示msg.what = -1;msg.getData().putString("error", "下载失败");//如果下载错误,显示提示失败!handler.sendMessage(msg);}}}).start();//开始}}6.到此为止运行会报错,因为没有向sdcard的协数据的权限,访问Internet的权限这需要在AndroidManifest.xml配置具体代码如下:<?xml version="1.0"encoding="utf-8"?><manifestxmlns:android="/apk/res /android"package="com.smart.activoty.download"android:versionCode="1"android:versionName="1.0"><application android:icon="@drawable/icon" android:label="@string/app_name"><activityandroid:name=".SmartDownloadActivity"android:label="@string/app_name"> <intent-filter><actionandroid:name="android.intent.action.MAIN"/><categoryandroid:name="UNCHER"/> </intent-filter></activity></application><uses-sdk android:minSdkVersion="8"/><!-- 访问internet权限 --><uses-permissionandroid:name="android.permission.INTERNET"/><!-- 在SDCard中创建与删除文件权限 --><uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FI LESYSTEMS"/><!-- 往SDCard写入数据权限 --><uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_S TORAGE"/></manifest>。
Android测试如何进行多线程和并发性测试
Android测试如何进行多线程和并发性测试一、引言在当今移动应用开发领域,Android操作系统广泛应用,为了保证应用在多终端、多用户场景下的稳定性及性能,进行多线程和并发性测试是非常重要的。
本文将介绍如何进行Android多线程和并发性测试,以保证应用程序的稳定性与用户体验。
二、多线程测试介绍多线程测试是一种在同一时间内运行多个线程的测试方法,可用于模拟实际应用中多个线程同时运行的情况,以检测应用程序在多线程环境下的稳定性和性能。
1. 需求分析在进行多线程测试之前,首先需要进行需求分析。
确定应用程序中需要同时进行多线程操作的场景,例如同时进行网络请求和数据读取,同时进行UI渲染和数据计算等。
2. 设计多线程测试用例根据需求分析,设计多线程测试用例。
测试用例应包括多个不同线程同时进行的操作,以及验证结果的检查点。
例如,创建多个线程进行网络请求,检查返回的数据是否正确,是否有数据丢失等。
3. 编写测试代码根据设计的测试用例,编写测试代码。
使用Android提供的多线程编程接口,例如使用Thread类和Runnable接口来创建多个线程,或者使用AsyncTask等异步任务类。
4. 执行多线程测试在真实设备或模拟器上执行多线程测试,观察应用程序在多线程环境下的执行情况。
记录测试结果,并进行问题分析和修复。
5. 优化多线程性能根据测试结果,优化应用程序的多线程性能。
例如使用线程池管理线程、合理调度线程的执行顺序、避免线程之间的竞争条件等。
三、并发性测试介绍并发性测试是一种测试方法,用于评估应用程序在多用户同时访问的情况下的性能和稳定性。
在Android应用开发中,了解应用程序在并发访问情况下的表现是非常重要的。
1. 确定测试场景在进行并发性测试之前,首先需要确定测试场景。
根据应用的实际使用情况,确定多用户同时访问的情况。
例如,在社交应用中,多个用户同时进行消息发送和接收。
2. 设置测试环境为了模拟多用户同时访问的情况,需要设置合适的测试环境。
Android系统级小知识
Android 小知识集相关小知识。
一、Log 相关小知识。
1、产生 Log 文件的情况:a、程序异常退出;b、程序强制退出;d、程序无响应 (ANR) 。
2、产生 ANP(Application No Responsing)的情况:a、在操作界面时,等待响 应时间超过 5 秒;b、在 Handler 中处理 Message 超过 10 秒。
3、Log 文件存放在/data/Log 目录(虚拟机上没有此文件,真机上有) 。
; 4、Log 文件组成:a、系统基本信息(CPU 使用情况,内存使用情况等信息) b、事件信息(同 DDMS 中的 Log 一样) ;c、虚拟机信息(进程信息,线程 信息等) 。
5、Log 分为 5 类:V(verbose) 、D(debug) 、I(Info) 、W(warning) 、E(Error) 。
前面两个一般只是在编程的有,在实际安装的时候没有。
Log 的级别从左到 右依次升高。
二、进程生命周期(Progress Lifecycle) 进程生命周期( ) 1、Android 的进程分为 5 类:a、Foreground Progress;b、Visible Progress; c、Service Progress;d、Background Progress;e、Empty Progress。
优先级从 a 到 b 逐渐降低。
三、Manifest 的介绍 1、Manifest 的解析:a、系统启动的时候,PackagedManageService 读取所有应用 程序的 Manifest 信息,并且将其映射到共享内存中以供查询;b、应用程序启 动的时候,Launcher 进行系统级判断,如最小 SDK 等;c、四大组件在需要 的时候才实例化。
四、Activity、Window、View 的关系 、 、 1、一个 Activity 构造的时候一定会构造一个 Window(PhoneWindow) (Window 并不是显示的视图) ,并且只有一个。
activity.runonuithread 的理解
activity.runonuithread 的理解在Android开发中,`activity.runOnUiThread` 是一种在UI线程上执行代码块的方法。
Android UI框架要求所有与UI相关的操作必须在主线程(UI线程)上执行,以确保界面更新的同步性和一致性。
如果在非UI线程上执行与UI相关的操作,可能会导致应用程序崩溃或出现不可预测的行为。
`activity.runOnUiThread` 提供了一种在后台线程(非UI线程)中安全地更新UI的方式。
它接受一个`Runnable`对象,该对象包含要在UI线程上执行的代码块。
当调用`activity.runOnUiThread` 时,它会将`Runnable` 对象提交到主线程的消息队列中,以确保在UI线程上执行。
以下是一个简单的示例,演示了如何使用`activity.runOnUiThread` 在后台线程中更新UI:```javanew Thread(new Runnable() {@Overridepublic void run() {// 在后台线程中执行一些耗时操作// 需要在UI线程上更新UI的操作activity.runOnUiThread(new Runnable() {@Overridepublic void run() {// 在UI线程上更新UI的代码// 例如,更新TextView的文本或执行其他UI操作textView.setText("Updated text on UI thread");}});}}).start();```在这个例子中,后台线程执行一些耗时操作,然后通过`activity.runOnUiThread` 将更新UI 的代码块提交到UI线程,确保在正确的上下文中更新UI。
这是一种处理多线程问题的常见模式,以避免UI更新冲突和其他与多线程相关的问题。
Android应用程序UI硬件加速渲染环境初始化过程分析
在Android应用程序中,我们是通过Canvas API来绘制UI元素的。
在硬件加速渲染环境中,这些Canvas API调用最终会转化为Open GL API调用(转化过程对应用程序来说是透明的)。
由于Open GL API调用要求发生在Open GL 环境中,因此在每当有新的Activity窗口启动时,系统都会为其初始化好Open GL环境。
这篇文章就详细分析这个Open GL环境的初始化过程。
Open GL环境也称为Open GL渲染上下文。
一个Open GL渲染上下文只能与一个线程关联。
在一个Open GL渲染上下文创建的Open GL对象一般来说只能在关联的Open GL线程中操作。
这样就可以避免发生多线程并发访问发生的冲突问题。
这与大多数的UI架构限制UI操作只能发生在UI线程的原理是差不多的。
在Android 5.0之前,Android应用程序的主线程同时也是一个Open GL 线程。
但是从Android 5.0之后,Android应用程序的Open GL线程就独立出来了,称为Render Thread,如图1所示:图1 Android应用程序Main Thread和Render Thread Render Thread有一个Task Queue,Main Thread通过一个代理对象Render Proxy向这个Task Queue发送一个drawFrame命令,从而驱使Render Thread执行一次渲染操作。
因此,Android应用程序UI硬件加速渲染环境的初始化过程任务之一就是要创建一个Render Thread。
一个Android应用程序可能存在多个Activity组件。
在Android系统中,每一个Activity组件都是一个独立渲染的窗口。
由于一个Android应用程序只有一个Render Thread,因此当Main Thread向Render Thread发出渲染命令时,Render Thread要知道当前要渲染的窗口是什么。
android高级开发面试题
android高级开发面试题作为Android开发者,掌握高级开发知识是非常重要的。
下面是一些涵盖了Android高级开发领域的面试题,希望对你的面试准备有所帮助。
一、Android基础知识1. 请解释Android中的四大组件是什么,并简要描述它们的作用。
2. 什么是Intent?请解释显式Intent和隐式Intent的区别。
3. 请解释Activity之间的生命周期方法,并描述其调用顺序。
4. 什么是Fragment?请解释Fragment的作用以及与Activity之间的关系。
5. 描述Android的存储选项,如Shared Preferences,SQLite数据库和文件存储。
6. 请解释Android中的内容提供者(Content Provider)的作用,以及如何通过内容提供者访问数据。
二、多线程和异步编程1. 什么是主线程(主UI线程)?为什么不能在主线程中进行耗时操作?2. 描述AsyncTask的作用以及基本使用方法。
3. 请解释Handler和Looper的概念,并描述它们在Android中的使用方式。
4. 什么是线程同步?请解释如何在Android中实现线程同步。
5. 请解释Android中的HandlerThread,并描述它与普通线程的区别。
6. 描述一下使用RxJava进行异步编程的优势,并简要说明如何在Android中使用RxJava。
三、性能优化和内存管理1. 请解释ANR(应用程序无响应)是什么?以及如何避免ANR的发生。
2. 描述一下Android中的内存管理方式,并提出一些建议来优化Android应用程序的内存使用。
3. 如何检测和解决Android应用程序中的内存泄漏问题?4. 请解释什么是视图绘制(View Rendering),并提出一些建议来优化Android应用程序的视图绘制性能。
5. 请解释Android中的Bitmap对象,并提出一些优化Bitmap内存使用的方法。
android threadloop的用法 -回复
android threadloop的用法-回复标题:深入理解与使用Android中的ThreadLoop在Android开发中,多线程编程是一个非常重要且常见的技术。
其中,ThreadLoop(也被称为Looper和Handler机制)是Android系统中实现消息驱动模型的核心组件,它允许我们在不同的线程之间进行通信和数据交换。
以下我们将详细解析ThreadLoop的用法,从理论到实践,一步步进行讲解。
一、ThreadLoop的基本概念ThreadLoop,简单来说,就是一个线程的消息循环机制。
在一个线程中,当我们创建了一个Looper对象并调用了它的prepare()方法后,这个线程就进入了消息循环状态。
在这个状态下,线程会不断地检查MessageQueue(消息队列)中是否有新的消息,如果有,就取出并处理。
二、创建ThreadLoop1. 初始化Looper:在需要启动消息循环的线程中,首先需要调用Looper.prepare()方法来初始化Looper。
javaLooper.prepare();2. 创建Handler:然后,我们需要创建一个Handler对象,并重写handleMessage()方法,这个方法将在接收到消息时被调用。
javaHandler handler = new Handler() {Overridepublic void handleMessage(Message msg) {处理消息}};3. 启动Looper:最后,调用Looper.loop()方法启动消息循环。
javaLooper.loop();三、发送消息有了Looper和Handler之后,我们就可以在任何地方通过Handler向消息队列发送消息了。
发送消息的方法主要有以下两种:1. sendMessage():发送一个包含what和obj参数的消息。
javahandler.sendMessage(new Message());2. post():发送一个Runnable任务。
android 协程切换线程原理
android 协程切换线程原理
在 Android 中,协程是基于线程的,可以在不同的线程之间进
行切换。
协程的切换线程的原理如下:
1. 协程是基于 Kotlin 的协程库实现的,而 Kotlin 协程是基于
一个称为“Continuation”的概念的。
Continuation 是一个抽象类,用于保存协程的状态,并且可以在需要时恢复协程的执行。
2. 当一个协程需要切换线程时,它首先会在当前线程创建一个Continuation 对象,保存当前协程的状态。
3. 然后,协程会将需要切换到的线程作为参数传递给Continuation 对象的 `resumeWith` 方法。
4. 在 `resumeWith` 方法中,Continuation 会调用与目标线程相
关的适配器,该适配器负责将协程的执行转移到目标线程,并在目标线程上恢复协程的执行。
适配器可以是 Android 的
`Handler`、`Looper`、`Executor` 等。
5. 一旦协程在目标线程上恢复执行,它将继续执行下一个挂起点(`suspend` 函数)之前的代码。
利用协程的切换线程机制,开发者可以在多个线程之间进行无缝的切换,使协程可以在任何线程上执行耗时操作,而不会阻塞 UI 线程,从而提供更好的用户体验。
【朝花夕拾】Android多线程之(三)runOnUiThread篇——程序猿们的贴心小棉袄
【朝花⼣拾】Android多线程之(三)runOnUiThread篇——程序猿们的贴⼼⼩棉袄runOnUiThread()的使⽤以及原理实在是太简单了,简单到笔者开始都懒得单独开⼀篇⽂章来写它。
当然这⾥说的简单,是针对对Handler⽐较熟悉的童鞋⽽⾔的。
不过⿇雀虽⼩,五脏俱全,runOnUiThread()好⽍也算得上是⼀⽅诸侯,在⼦线程切换到主线程的众多⽅法中,有着⾃⼰的⼀席之地,所以,必须得给它单独列传。
好了,闲话休提,⾔归正传。
runOnUiThread()是Activity类中的⽅法,它⽤于从⼦线程中切换到主线程来执⾏⼀些需要再主线程执⾏的操作。
这⾥先直接看⼀个例⼦,看看它是如何使⽤的:1public class MainActivity extends AppCompatActivity {2private TextView textView;3 @Override4protected void onCreate(Bundle savedInstanceState) {5super.onCreate(savedInstanceState);6 setContentView(yout.activity_main);7 textView = findViewById(_test);8new Thread(new Runnable() {9 @Override10public void run() {11//do something takes long time in the work-thread12 runOnUiThread(new Runnable() {13 @Override14public void run() {15 textView.setText("test");16 }17 });18 }19 }).start();20 }21 }简单吧,在⼦线程中直接调⽤runOnUiThread⽅法,第15⾏就切换到主线程了,直接修改UI。
runonuithread 详解
runonuithread 详解runOnUiThread是Android中一个常用的方法,用来在主线程(UI 线程)中执行一些任务。
这个方法通常被用来更新 UI 或者处理一些和 UI 相关的操作。
在 Android 中,UI 线程是一个非常重要的线程。
它负责响应用户的操作,并且更新界面。
如果在 UI 线程上执行一些耗时的操作,就会导致 UI 界面卡顿,影响用户体验。
因此,我们需要使用runOnUiThread 方法来将一些耗时的操作放到子线程中执行,从而避免阻塞 UI 线程。
runOnUiThread 方法的使用非常简单,只需要将需要在 UI 线程中执行的任务放到一个 Runnable 对象中,然后调用 runOnUiThread 方法即可:```runOnUiThread(new Runnable() {@Overridepublic void run() {// 在主线程中执行的任务}});```除了 runOnUiThread 方法外,还有一些其他的方法可以用来在主线程中执行任务。
比如,可以使用 Handler、AsyncTask 等方式来实现。
但是在实际开发中,runOnUiThread 方法是最常用、最简单的方式。
需要注意的是,runOnUiThread 方法只能在 Activity 中使用。
如果需要在 Fragment 或者其他组件中使用,需要先获取到Activity 对象,然后调用 Activity 的 runOnUiThread 方法。
综上所述,runOnUiThread 方法是 Android 开发中一个非常常用、简单的方法,可以帮助我们避免阻塞 UI 线程,提升用户体验。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
AndroidManifest.xml
<intent-filter>
<action android:name="android.intent.action.SIMEDIT" />
<category android:name="android.intentቤተ መጻሕፍቲ ባይዱcategory.DEFAULT" />
(1) 定义一个信息对象,该信息对象可以发送给handler对象来处理
(2) 可以调用Message.obtain() 或者Handler.obtainMessage()来实例化Messsage对象。
4.MessageQueue
维护一个消息队列,该列表中的消息通过Looper对象来分配的,
(3) View.postDelayed(Runnable,long)
--------->添加Runnable对象到消息队列,并在指定时间之后运行,Runnable
对象将在UI中运行。
(4) Handler
handler自己有几种方式:
1,用来处理消息和线程,每个handler实例关联一个单线程和该线程
surfaceHolder.addCallback(this);
}
protected void paint(Canvas canvas) {
//这里的代码跟继承View时OnDraw中一样
}
}
}
Intent在Android中的几种用法
如果是从BroadcastReceiver 启动一个新的Activity , 不要忘记i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
(1)隐式查找type
示例代码:
uri: content://simcontacts/simPeople/(id)
intent = new Intent("android.intent.action.SIMEDIT",uri);
startActivity(intent);
>>>> sendMessage(Message)
>>>> sendMessageAtTime(Message,long)
>>>> sendMessageDelayed(Message,long)
>>>> handlerMessage(Messsage)
3.Messgae
这时候你需要创建一个继承了android.os.Handler的子类,并重写handleMessage(Message msg)方法。android.os.Handler是能发送和处理消息的,你需要在Activity中发出更新UI的消息,然后再你的Handler(可以使用匿名内部类)中处理消息(因为匿名内部类可以访问父类变量, 你可以直接调用View对象中的invalidate()方法 )。也就是说:在新线程创建并发送一个Message,然后再主线程中捕获、处理该消息。
}
}
复制代码
当调用线程处于空闲状态时,会调用onDraw,刷新界面,也就是说,该函数仅是标记当前界面过期,并不直接负责刷新界面()
public class PuzzleView extends SurfaceView implements SurfaceHolder.Callback{
程序会很据data中的uri去查找匹配的type(必须的)
provider中的getType()
case SIM_PEOPLE_ID:
return "vnd.android.cursor.item/sim-contact";
}
@Override
public boolean onTouchEvent(MotionEvent event) {
invalidate();
//处理逻辑
invalidate(); //刷
-------->在UI线程里运行指定的动作,如果当前线程是UI线程,则立刻被执行
,如果是主线程,则该动作被发送到UI线程的事件队列中,等待处理。
(2) View.post(Runnable)
--------->添加Runnable对象到消息队列,Runnable对象在UI线程中被执行。
Intent setClass(Context packageContext, Class<?> cls)
Intent 应该算是Android中特有的东西。你可以在Intent中指定程序 要执行的动作(比如:view,edit,dial),以及程序执行到该动作时所需要的资料 。都指定好后,只要调用startActivity(),Android系统 会自动寻找最符合你指定要求的应用 程序,并执行该程序。
menu.add(0, 0, 0, R.string.importFromSim)
.setIcon(R.drawable.ic_menu_import_contact)
.setIntent(importIntent);
2. 指定act ion, da ta和type
Intent i=new Intent(context,Receivered.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
1. 指定act ion 和type
Intent setComponent(ComponentName component)
Intent setClassName(Context packageContext, String className)
Intent setClassName(String packageName, String className)
下面列出几种Intent 的用法
的一个消息队列。
2,handler可以执行一个线程对象(Runnable实例)也可以发送和处理消息。
>>>> post(Runnable)
>>>> postAtTime(Runnable,long)
>>>> postDelayed(Runnale,long)
>>>> sendEmptyMessage(int)
}
public void repaint() {
Canvas c = null;
try {
c = surfaceHolder.lockCanvas();
2.使用多线程和不使用双缓冲
这种情况需要开启新的线程,新开的线程就不好访问View对象了。强行访问的话会报:android.view.ViewRoot$CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views.
。invalidate()函数重绘
public class PuzzleView extends View {
@Override
protected void onDraw(Canvas canvas) {
...
android 多线程
1.刷新View类的视图组件
(1).invalidata() --------------->必须在UI线程中调用
(2).postInvalidata() ------------>可以在子线程中调用
2.子线程访问主线程的方法:
(1) Activity.runOnUiThread(Runnable)
3.使用多线程和双缓冲
Android中SurfaceView是View的子类,她同时也实现了双缓冲。你可以定义一个她的子类并实现SurfaceHolder.Callback接口。由于实现SurfaceHolder.Callback接口,新线程就不需要android.os.Handler帮忙了。SurfaceHolder中lockCanvas()方法可以锁定画布,绘制玩新的图像后调用unlockCanvasAndPost(canvas)解锁(显示),还是比较方便得。
调用Looper.myQueue()方法可以获得一个MessageQueue对象。
Android中对View的更新有很多种方式,使用时要区分不同的应用场合。我感觉最要紧的是分清:多线程和双缓冲的使用情况。
1.不使用多线程和双缓冲
这种情况最简单了,一般只是希望在View发生改变时对UI进行重绘。你只需在Activity中显式地调用View对象中的invalidate()方法即可。系统会自动调用 View的onDraw()方法。
// SIM import
Intent importIntent = new Intent(Intent.ACTION_VIEW);
importIntent.setType("vnd.android.cursor.item/sim-contact");
importIntent.setClassName("com.android.phone", "com.android.phone.SimContacts");
private SurfaceHolder surfaceHolder;