Android线程处理

首先,我们要明确一点Android的耗时操作是绝对不允许在主线程(Main Tread)里面执行的!这些耗时操作,比如下载或上传图片、获取或上传大量的字符串、视频的传输等等。当一个控件的点击事件涉及到这些耗时操作时,那么意味着控件的响应将变得很慢,当然这只是理想状态的,而实际上,当出现这种情况时,程序是会出现ANR(程序不响应)的,那么程序会崩溃掉。Android的主线程基本上是用来响应控件的点击事件而更新UI的,所以我们的耗时操作是需要放到子线程执行的,这里我再添加一点,严格意义上讲,Anroid的子线程是不能够更新UI的,具体见(http://blog.csdn.net/zhao_csdn_8/article/details/64126195)。

接下来,我们借两张图来了解一下Handler机制:
这里写图片描述

Handler机制包括三个部分:Handler、Looper、MessageQueue,这三个部分构成一个处理循环,Handler即处理,Looper是一个死循环,MessageQueue是消息队列,如下:
这里写图片描述

这里边就有着许多步骤:

Handler回调用sendxxx方法将延时操作所获取的数据发送出去。
然后Handler再调用enqueueMessage(Message msg, long when)方法将消息入队列。
当looper轮询到消息时,Looper调用next() ,将消息移出队列。
然后Looper回调Handler的dispatchMessage方法将消息分发给Handler的实例去处理。

Handler有如下的处理方法……

方法一:new Handler().sendMessage()

……
//如下是一个实现异步加载图片的实例……

private Handler handler=new Handler(){//处理消息
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what)
            {
                case 0:
                    getc.setImageBitmap((Bitmap)msg.obj);
//设置图片显示
                    break;
default:
break;
}
            super.handleMessage(msg);
        }
    };


public void getIdentifyingCode(){//显示验证码
new Thread(){
            @Override
            public void run() {
                super.run();
                Bitmap bitmap=LoadBitmap();//延时操作
                Message msg=Message.obtain();
                msg.what=0;
                msg.obj=bitmap;
                handler.sendMessage(msg);
            }
        }.start();
    }
    public Bitmap LoadBitmap(){//异步线程加载验证码的图片
        Bitmap bitmap=null;
        String urlString="获取图片的URL地址";
        URLConnection con= null;
        try {
   con = new URL(urlString).openConnection();
   InputStream is=new BufferedInputStream(con.getInputStream());
   bitmap= BitmapFactory.decodeStream(is);
   is.close();
        } catch (IOException e) {
            e.printStackTrace();}
        if(bitmap==null) Toast.makeText(Login.this,"服务器连接错误,无法获取验证码",Toast.LENGTH_LONG); return bitmap;}

另外,我在用此方法实现账号登录操作的时候,我在OnClick()里实现一段如下:

public class MainActivity extends Activity {
protected String jsonData;
……
Handler handler=new Handler(){
@Override
public void handMessage(Object msg){
……
jsonData=msg.toString();
}
}
……
case R.id.login:
getLoginData();//此函数里面开启线程获取数据
If(用jsonData做出响应的判断)
执行相应的操作
break;
……
}

然后会在if判断处报出空指针错误,原因是:其实在getLogin()执行时,执行了thread.start(); 但是handler并不是马上执行(相对而言的),而是在执行完case R.id.login:……这一代码块,handler才会执行,即主线程是优先执行的,所以在使用全局变量jsonData作为条件判断时,这个字符串根本就没有被赋值,所以会报出空指针错误。
于是就只能将getLoginData()后面的操作放到handler里面执行。

方法二:使用Runable
//使用runOnUiThread

public class MainActivity extends Activity {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
new Thread(){
public void run() {
runOnUiThread(new Runnable() {
public void run() {
//此处可执行一般的耗时操作(小于5秒)
tv.setText("你好!!!");
}
});
};
}.start();
}
}
//使用handler.post(……)
public class MainActivity extends Activity {
private TextView tv;
private Handler handler=new Handler(); 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
new Thread(){
public void run() {
Handler.post(new Runnable() {
public void run() {
//此处可执行一般的耗时操作(小于5秒)
tv.setText("你好!!!");
}
});
};
}.start();
}
}

//继承Runable接口(postDelayed方法)

public class MainActivity extends Activity {
private Imageview im;
Private int images[]={R.drawable.image1,R.drawable.image2,
R.drawable.image2,};
private int index;
private MyRunable myRunable=new MyRunable();
private Handler handler=new Handler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
im = (ImageView) findViewById(R.id.im);
hander.postDelayed(myRunable,1000);//执行……
}
class MyRunable implements Runable{
@Override
public void run(){
index++;
Index=index%3//实现三张图片的轮流播放
im.setImageResource(images[index]);
hander.postDelayed(myRunable,1000);
}
}
}

这三种方式的基本差不多,只是用到了不同的函数,不同的函数在底层调用的sendxxx方法和postxxx方法有所不同,本人还没学的那么深入,见谅。
对于异步处理,AsyncTask是一个比较好的选择,适合初学者使用,结构明朗易懂,只要是三个函数 onPre(),onPost()以及doback()等等(简略的写),下面为
AsyncTask的基本结构

onPre()用于前期的处理,doBack()用于开启异步线程,此
数可将所得结果返回出去并由onPost()接收进行UI的更新。AsyncTask(argc1,argc2,argc3)类有三个传入参数类型,argc1起始传入>>参数,argc2为中间量的返回参数类型,一般用于耗时操作进度的记录,
argc3为doBack()的返回值类型,AsyncTask(argc1,argc2,argc3)
表示传入一个String类型的数据,不反回中间值,doBack()返回一个json数组,用 new MyAsyncTask().excute(传入参数) 启动异步线程。

class getDeptList extends AsyncTask<String,Void,JSONArray>{
              @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }
        @Override
        protected JSONArray doInBackground(String... params) {
String data=getDeptlData(params[0]);//延时操作
try {
      JSONObject jsonObject=new JSONObject(data);
       dataArray=new JSONArray(jsonObject.getString("data"));
       return dataArray;
   } catch (JSONException e) {
       e.printStackTrace();
   }
    return null;
 }
@Override
protected void onPostExecute(JSONArray jsonArray) {
   super.onPostExecute(jsonArray);
   if(jsonArray==null){
     Toast.makeText(DeptList.this,"部门列表为空……",Toast.LENGTH_LONG).show();
    }
   else{
       //适配
DeptListAdapter     deptListAdapter=newDeptListAdapter
(DeptList.this,jsonArray);
      mList.setAdapter(deptListAdapter);
            }
        }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android线程是指在Android操作系统中运行的线程线程是一种轻量级的执行单元,它可以在程序中并发地执行多个任务。Android系统中有两种类型的线程:UI线程和后台线程。 1. UI线程 UI线程是指在Android应用程序中与用户交互的主线程,也称为主线程。它负责处理用户界面的所有事件和更新UI界面。在UI线程中,应该避免执行长时间的操作,否则会导致UI界面无响应。 2. 后台线程 后台线程是指在Android应用程序中不与用户交互的线程。后台线程负责执行耗时的操作,如网络请求、文件读写等。在后台线程中执行操作可以避免UI线程的阻塞,提高用户体验。 3. 线程的创建和启动 在Android应用程序中,可以通过继承Thread类或实现Runnable接口来创建线程。创建线程的步骤如下: a. 创建Thread或Runnable对象。 b. 调用Thread类的start()方法或将Runnable对象传递给Thread类的构造方法,并调用start()方法。 4. 线程的同步 在多线程环境下,可能会出现数据竞争和线程安全问题。为了保证线程安全,需要使用同步机制。在Android应用程序中,可以使用synchronized关键字或Lock接口来实现同步。 5. 线程的停止 停止线程是一个比较复杂的问题,因为线程的停止需要考虑线程的安全性和资源的释放。在Android应用程序中,可以通过设置标志位或调用Thread类的interrupt()方法来停止线程。 总之,Android线程Android应用程序中非常重要的一个概念,它可以提高程序的并发性和响应性。在编写Android应用程序时,需要注意线程的创建、同步和停止,以确保程序的正确性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值