❶ Android开发之路-多线程
多线程作为Android开发中相对而言较为高阶的知识,其中用到相关的知识点是非常的多,所以在我们需要进行设计或者写多线程的代码就必须要进行相对谨慎的处理,这样就由必要对其要有着比较系统化的认知
我们一般将Android应用分成为两种:主线程和工作线程;主线程主要是用来进行初始化UI,而工作线程主要是进行耗时操作,例如读取数据库,网络连接等
Android系统是以进程为单位来对应用程序资源进行限制,这个问题的可以解释为:一个进程最多能够开几个线程?最好能开几个?但实则这个是没有上限这一说,主要是因为资源的限制
Android中关于主线程的理解:Android的主线程是UI线程,在Android中,四大组件运行在主线程中,在主线程中做耗时操作会导致程序出现卡顿甚至出现ANR异常,一个.
在一个程序中,这些独立运行的程序片断叫作“线程”(Thread),利用它编程的概念就叫作“多线程处理”。多线程处理一个常见的例子就是用户界面。
线程总的来就是进程的一个实体,是CPU进行分派和调度的基本单位,拥有着比进程更小且能够独立运行的基本单位,线程本身基本上是不拥有系统资源,仅拥有一点在运行过程中必须拥有的资源,但它可与同属一个进程中的其他进程进行共享其所拥有的所有资源
线程状态有些地方将之分为5中状态,而且在java Jdk中线程被其定义为6中状态,我们可以对其进行类比
普遍定义的5中状态:新建,就绪,运行,阻塞, 死亡
Java Jdk 定义状态
线程阻塞是指在某一时刻的某一个线程在进行运行一段代码的情况下,突然另一个线程也要进行运行,但在运行过程中,那个线程执行完全运行之前,另一个线程是不可能获取到CPU的执行权,就会导致线路阻塞的出现
死锁也称之为抱死,意思就是说一个进程锁定了另外一个进程所需要的页或表是,但第二个进程同时又锁定了第一个进程所需的一页,这样就会出现死锁现象
简要介绍实现线程的三种方式:继承Thread,实现runnable,实现callable。这里有一点需要注意的是,实现callable是与线程池相关联的而callable很重要的一个特性是其带有返回值。当我们只需实现单线程时实现runnable更加利于线程程序的拓展
在线程开启之前进行调用 thread.setDaemon(true); 将thread设定成当前线程中的守护线程 使用案例
线程让步【yield方法】让当前线程释放CPU资源,让其他线程抢占
这种具体某个对象锁 wait & notify 方法与Condition 的 await以及signal方法类似; 全面这种方法的阻塞等待都可以是释放锁,而且在唤醒后,这种线程都是能够获取锁资源的,而这个门栓就跟阀门类似
❷ android-Service和Thread的区别
Service 是 Android 中四大组件之一,在 Android 开发中起到非常重要的作用。
Service(服务)是一个没有用户界面的在后台运答行卖行执行“耗时操作”的应用组件。其
他应用组件能够启劢 Service,并且当用户切换到另外的应用场景,Service 将持续在
后台运行。另外,一个组件能够绑定到一个 service 与之交互(IPC 机制),例如,一
个 service 可能会处理网络操作,播放音乐,操作文件 I/O 戒者不内容提供者
(content provider)交互,所有这些活动都是在后台进行。
关键它是有生命周期。
service用法:
(1)创建一个类继承service
(2)在清单文件中去注册
(3)开始使用
Thread简介:
1.由于线程是依赖进程而存在的,所以我们应该先创建一个进程出来。但是进程是由系统创建的,所以我们需要带亏调用系统功能创建一个进程。但是Java不具备直接调用系统功能的能力,所以,我们没办法直接实现多线程程序。
然而,Java可以直接去调用C/C++写好的程序来实现多线程程序。再由C/C++去调用系统功能创建进程,然后由Java去调用这样的东西。所以,Java提供能实现多线程的底层类库。例如:Thread类。
2.生命周期:任何线程(包括主线程:main线程)在其生命周期中,都有5中状态:创建、就绪、运行、阻塞、终止。
3.多线程实现:
(1)实现线程的方式一:
1.自定义一个类 ,继承Thread类
2.自定义类中重写Thread的run方法
3.创建自定义类对象
4.启动线程
(2)实现线程的方式二:
实现Runnable接口:
1.自定义类实现Runnable接口
2.在自定义清逗类中实现run方法
3.创建自定义类对象
4.创建Thread类对象,并且将自定义类中的对象当做构造参数传递
5.启动线程
❸ 如何解决空指针异常和 ThreadException 中的错误android
空指针异常: 可以直接在可差洞唯能出现空指针的代码处 try catch一下,你也可以这样做:在用到可能出现空指针的 变量或者对象处,先增加一个判空颤乱处理(比如:if(textutil.isempty(str) { })
对于ThreadException:对于线程的异常,在android中,google禁止了在主线程中进行访问网络等一些耗时操作(否则就会出现这种异常)。可以开个子虚培线程(workThread)在里面进行访问网络,用异步任务或者 handler来处理。
❹ 程序Android中Handler和Timer还有Thread的最大区别是什么
我个人觉得thread是者禅用来后台数据处理的,例如请求网络信息,文件读写等,哪团而handler正是thread和Activity之间的桥梁,负责吧thread得到李嫌橘的信息传递给activity,从而完成UI(界面)的刷新。
❺ Android中的Handler详解以及和Thread的区别
handler主要用于线程间通信,举一个常见的场景,在一个新弯掘开的thread中请求网络,等待网络请求成功后更新界面。此州闹和时,由于更新UI的操作不能在新开的thread中完册盯成,需要handler发送消息到主线程中来执行。
例如:new Thread(new Runnable(){
@override
public void run(){
Object result=queryWeather();
Message message = handler.obtainMessage();
message.obj = result;
handler.sendMessage(0);
}
}).start();
在主线程中定义handler,Handler handler = new Handler(){
@override
public void handleMessage(Message msg){
switch(msg.what){
case 0:
//此处为收到thread发来的消息,在此更新textView
textView.setText(msg.obj.getContent());
break;
}
}
}
大概就是这个用途,手敲的代码可能会有错误,意思应该明白
❻ Android中的Handler详解以及和Thread的区别
一、Handler的定义:
主要接受子线程发送的数据, 并用此数据配合主线程更新UI.
解释: 当应用程序启动时,首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作。 如果此时需要一个耗时的操作,例如: 联网读取数据, 或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,,会收到Android系统的一个错误提示 "强制关闭". 这个时候我们需要把这些耗时的操作,放在一个子线程中,因为子线程涉及到UI更新,,Android主线程是线程不安全的,也就是说,更新UI只能在主线程中更新,子线程中操作是危险的. 这个时候,Handler就出现了.,来解决这个复杂的问题 , 由于Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。
二、Handler一些特点
handler可以分发Message对象和Runnable对象到主线程中, 每个Handler实例,都会绑定到创建他的线程中(一般是位于主线程),
它有两个作用: (1): 安排消息或Runnable 在某个主线程中某个地方执行, (2)安排一个动作在不同的线程中执行
Handler中分发消息的一些方法
[html] view plain
post(Runnable)
postAtTime(Runnable,long)
postDelayed(Runnable long)
sendEmptyMessage(int)
sendMessage(Message)
sendMessageAtTime(Message,long)
sendMessageDelayed(Message,long)
以上post类方法允许你排列一个Runnable对象到主线程队列中,
sendMessage类方法, 允许你安排一个带数据的Message对象到队列中,等待更新.
三、Handler实例
(1) 子类需要继承Hendler类,并重写handleMessage(Message msg) 方法, 用于接受线程数据
以下为一个实例,它实现的功能为 : 通过线程修改界面Button的内容
[html] view plain
public class MyHandlerActivity extends Activity {
Button button;
MyHandler myHandler;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handlertest);
button = (Button) findViewById(R.id.button);
myHandler = new MyHandler();
// 当创建一个新的Handler实例时, 它会绑定到当前线程和消息的队列中,开始分发数据
// Handler有两个作用, (1) : 定时执行Message和Runnalbe 对象
// (2): 让一个动作,在不同的线程中执行.
// 它安排消息,用以下方法
// post(Runnable)
// postAtTime(Runnable,long)
// postDelayed(Runnable,long)
// sendEmptyMessage(int)
// sendMessage(Message);
// sendMessageAtTime(Message,long)
// sendMessageDelayed(Message,long)
// 以上方法以 post开头的允许你处理Runnable对象
//sendMessage()允许你处理Message对象(Message里可以包含数据,)
MyThread m = new MyThread();
new Thread(m).start();
}
/**
* 接受消息,处理消息 ,此Handler会与当前主线程一块运行
* */
class MyHandler extends Handler {
public MyHandler() {
}
public MyHandler(Looper L) {
super(L);
}
// 子类必须重写此方法,接受数据
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
Log.d("MyHandler", "handleMessage......");
super.handleMessage(msg);
// 此处可以更新UI
Bundle b = msg.getData();
String color = b.getString("color");
MyHandlerActivity.this.button.append(color);
}
}
class MyThread implements Runnable {
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.d("thread.......", "mThread........");
Message msg = new Message();
Bundle b = new Bundle();// 存放数据
b.putString("color", "我的");
msg.setData(b);
MyHandlerActivity.this.myHandler.sendMessage(msg); // 向Handler发送消息,更新UI
}
}
}
例外一个案例:
[html] view plain
package com.example.span.view;
import java.util.LinkedList;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Toast;
import com.example.span.view.domain.Block;
/**
* 2013-6-6 上午9:24:58
*
* @author 乔晓松
*/
public class GameView extends View {
public static boolean flag = true;
public static Block block;
public Handler handler;
public static int dir = 2;
public static final int DIRTOP = -1;
public static final int DIRLEFT = -2;
public static final int DIRDOWN = 1;
public static final int DIRRIGHT = 2;
public static int descount = 2;
public Canvas canvas;
public static Food food;
public LinkedList<Point> points = new LinkedList<Point>();
public LinkedList<Point> getPoints() {
return points;
}
public void setPoints(LinkedList<Point> points) {
this.points = points;
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
block = new Block(this);
for (int i = 0; i < 3; i++) {
Point point = new Point(block.getCx(), block.getCy());
block.setCx(block.getCx() - 20);
points.addLast(point);
}
food = new Food(this);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case DIRLEFT:
if (msg.what + descount != 0) {
descount = -2;
block.moveLeft();
} else {
block.moveRight();
}
break;
case DIRRIGHT:
if (msg.what + descount != 0) {
descount = 2;
block.moveRight();
} else {
block.moveLeft();
}
break;
case DIRTOP:
if (msg.what + descount != 0) {
descount = -1;
block.giveUp();
} else {
block.downLoad();
}
break;
case DIRDOWN:
if (msg.what + descount != 0) {
descount = 1;
block.downLoad();
} else {
block.giveUp();
}
break;
case -3:
Toast.makeText(getContext(), "Game Over", Toast.LENGTH_LONG)
.show();
new AlertDialog.Builder(getContext())
.setTitle("游戏提示")
.setMessage("Game Over")
.setPositiveButton("退出",
new DialogInterface.OnClickListener() {
@Override
public void onClick(
DialogInterface dialog,
int which) {
Thread.currentThread().stop();
}
})
.setNegativeButton("返回菜单",
new DialogInterface.OnClickListener() {
@Override
public void onClick(
DialogInterface dialog,
int which) {
Intent intent = new Intent();
intent.setAction("android.intent.action.MAI");
intent.addCategory("android.intent.category.LAUNCHER");
intent.setFlags(0x10200000);
intent.setComponent(new ComponentName(
"com.example.span",
"com.example.span.SpanActivity"));
getContext().startActivity(intent);
}
}).show();
break;
}
}
};
new Thread(new Runnable() {
@Override
public void run() {
while (flag) {
try {
Thread.sleep(500);
handler.sendEmptyMessage(dir);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
handler.sendEmptyMessage(-3);
}
}).start();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
System.out.println(keyCode);
return super.onKeyDown(keyCode, event);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.canvas = canvas;
food.chsw(canvas);
/*
* if (descount == 2) { chsw(); } else { if (points.contains(new
* Point(40, 40))) { System.out.println("吃掉食物了,,.."); } else { chsw(); }
* }
❼ 如何解决空指针异常和 ThreadException 中的错误android
在android2.3之后 在主线程首歼中必须使用者悄冲另一个线程 如handler机制,或者异步任务获取网络数据运昌
如果访问网络的操作 必须放在主线程中执行,那么 在oncreate()中添加
if (GetVersion.GetSystemVersion() > 2.3) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectDiskReads().detectDiskWrites().detectNetwork()
.penaltyLog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
.detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath()
.build());
}
这样 高版本中也可以在主线程中执行网络操作了
❽ 在android AndroidManifest.xml文件中怎样设置访问网络的权限
在<manifest标签下添加语句:
<uses-permission android:name="android.permission.INTERNET"/>
即可申请到访问网络的权限
拓展内容:
Android 6.0 运行时权限的介绍
在保护用户隐私方面:Android6.0为了更好的保护个人隐私,添加了运行时权限:分为两类,一类是Normal Permissions,这类权限不涉及个人隐私,不需要用户进行授权,比如手机震动,访问网络;一类是Dangerous Permissions,这类权限涉及个人隐私,需要用户进行授权,比如读取SD卡,访问通讯录等。
在用户操作方面:当执行敏感操作之前弹出对话框,请求权限,可以拒绝,可以同意;可以在设置页面对APP的权限进行查看,以及对单个权限进行授权或者解除授权。
❾ Android线程池的使用
在Android中有主线程和子线程的区分。主线程又称为UI线程,主要是处理一些和界面相关的事情,而子线程主要是用于处理一些耗时比较大的一些任务,例如一些网络操作,IO请求等。如果在主线程中处理这些耗时的任务,则有可能会出现ANR现象(App直接卡死)。
线程池,从名字的表明含义上我们知道线程池就是包含线程的一个池子,它起到新建线程、管理线程、调度线程等作用。
既然Android中已经有了线程的概念,那么为什么需要使用线程池呢?我们从两个方面给出使用线程池的原因。
在Android中线程池就是ThreadPoolExecutor对象。我们先来看一下ThreadPoolExecutor的构造函数。
我们分别说一下当前的几个参数的含义:
第一个参数corePoolSize为 核心线程数 ,也就是说线程池中至少有这么多的线程,即使存在的这些线程没有执行任务。但是有一个例外就是,如果在线程池中设置了allowCoreThreadTimeOut为true,那么在 超时时间(keepAliveTime) 到达后核心线程也会被销毁。
第二个参数maximumPoolSize为 线程池中的最大线程数 。当活动线程数达到这个数后,后续添加的新任务会被阻塞。
第三个参数keepAliveTime为 线程的保活时间 ,就是说如果线程池中有多于核心线程数的线程,那么在线程没有任务的那一刻起开始计时,如果超过了keepAliveTime,还没有新的任务过来,则该线程就要被销毁。同时如果设置了allowCoreThreadTimeOut为true,该时间也就是上面第一条所说的 超时时间 。
第四个参数unit为 第三个参数的计时单位 ,有毫秒、秒等。
第五个参数workQueue为 线程池中的任务队列 ,该队列持有由execute方法传递过来的Runnable对象(Runnable对象就是一个任务)。这个任务队列的类型是BlockQueue类型,也就是阻塞队列,当队列的任务数为0时,取任务的操作会被阻塞;当队列的任务数满了(活动线程达到了最大线程数),添加操作就会阻塞。
第哪歼纯六个参数threadFactory为 线程工厂 ,当线程池需要创建一个新线程时,使用线程工厂来给线程池提供一个线程。
第七个参数改含handler为 拒绝策略 ,当线程池使用有界队列时(也就是第五个参数),如果队列满了,任务添加到线程池的时候的一个拒绝策略。
可以看到FixedThreadPool的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出FixedThreadPool的几个特点:
可以看到CacheThreadPool的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出CacheThreadPool的几个特点:
可以看到ScheledThreadPoolExecutor的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出ScheledThreadPoolExecutor的几个特点:
可以看到SingleThreadExecutor的构建调用了ThreadPoolExecutor的构造函数。从上面的李咐调用中可以看出SingleThreadExecutor的几个特点:
❿ 为什么android在线程中请求网络数据会报错去掉线程就好了,有没有大神知道,急!!下面是加 了线程的代码
Toast.makeText(getApplicationContext(), result, 1).show();
本质是进行UI更新
需要在主线程下调用衫乱
网络访问的处理结果需要通过handler发送消息
然后在handler内对接收到的不同消陵粗息进行分别处理
handler是运行在主线程下, 可以进尺塌镇行UI更新