线程:后台异步任务AsyncTask

去五金店买个钻,不是因为我们需要钻,我们只需需要孔,既然五金店无法买孔,退而求其次,买打孔的工具。同样的对于后台线程,我们真正需要的是能够在UI主线程外进行处理,Android提供一个让程序员编写后台操作更为容易和透明AsyncTask。

使用AsyncTask,需要创建AsyncTask的资料,并实现其中的抽象方法以及重写某些方法。利用AsyncTask我们不需要自己来写后台线程,无需终结后台线程,例如stop()的方式。AsyncTask的方式对无限循环的方式并不太合适,可能更合适使用Runnable或者Thread。

对于初次使用的人,AsyncTask看起来有一些复杂。我们先学些AsyncTask的基本情况,然后给出一个小例子来验证。

AsyncTask

AsyncTask中有三个参数(例如class MyTask extends AsyncTask<参数1,参数2,参数3>{})

  • 参数1:向后台任务的执行方法传递参数的类型
  • 参数2:在后台任务执行过程中,要求主UI线程处理中间状态,通常是一些UI处理中传递的参数类型
  • 参数3:后台任务执行完返回时的参数类型

其中参数1和参数2是一个varags,例如String…,相当于String[]。

对于AsyncTask的使用步骤如下:

  • 创建一个AsyncTask的子类,对象创建时带参数(参数1,参数2,参数3
  • 调用对象的excute()时,将启动后台进程,执行doInBackground()的代码。excute()中所传递的参数类型在参数1中描述,属于范式定义
  • 如果我们希望在启动后台进程中,进行某些初始化的处理,可以override onPreExecute()方法,注意这些代码是在UI线程中执行的
  • 在执行完后台进程,我们需要进行某些处理,例如停止某些UI的动态画面,进度条消失等等,可以重写onPostExecute()方法,同样,这些代码也是在UI主线程中执行。其中将doInBackground()的返回值传递作为onPostExecute()参数中,其类型由参数3描述
  • 在执行后台进程中,如果需要需要向UI线程报告某个处理状态,可以通过publishProgress()来触发,这样在UI主线程中将执行重写后的onProgressUpdate()的代码,其中传递的参数的类型由参数2描述。

一个小例子

有一个ListView的小例子,一开始List中没有内容,通过一个AsyncTask逐步在List中加入条目。

1)XML文件:简单的ListView布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ... ...>

  <ListView android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />  
</LinearLayout>

2)例子代码

public class Chapter15Test3 extends ListActivity{
    //这里是List Item内容,在这个例子中,将在后台任务中逐个加入
    private static String[] items={"lorem", "ipsum", "dolor","sit", "amet", "consectetuer","adipiscing", "elit", "morbi","vel", "ligula", "vitae","arcu", "aliquet", "mollis","etiam", "vel", "erat","placerat", "ante","porttitor", "sodales","pellentesque", "augue","purus"};

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.chapter_8_test2);

        //在这个例子中,我们一开始并没有导入items的数据,注意item数据为新建的ArrayList,即无内容
        setListAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,new ArrayList<String>()));
        //步骤5:创建后台任务的对象,并通过execute()启动后台线程,调用doInBackground()的代码,execute中的参数类型为参数1,这里我们不需要传递任何内容
        new AddStringTask().execute();
    }
   
    //步骤1:创建AsyncTask子类,参数1是Void的范式类型,参数2是String的范式类型,参数3是Void 。其中参数1:向后台任务的执行方法传递参数的类型;参数2:在后台任务执行过程中,要求主UI线程处理中间状态,通常是一些UI处理中传递的参数类型;参数3:后台任务执行完返回时的参数类型
    private class AddStringTask extends AsyncTask<Void, String,Void>{
       //我们加入一个检测信息的方法,打印当前在哪个线程执行的信息
        private void printInfo(String info){
            Log.d("WEI", info + " : Tread is " + Thread.currentThread().getName());
        }

   
        //步骤2:实现抽象方法doInBackground(),代码将在后台线程中执行,由execute()触发,由于这个例子并不需要传递参数,使用Void...,具体书写方式为范式书写
        protected Void/*参数3*/ doInBackground(Void...params/*参数1*/) {
            for(String item : items){
                //步骤3:通知UI主线程执行相关的操作(在onProgressUpdate中定义)
                publishProgress(item/*参数2*/);
                printInfo("doInBackgound " + item);
                SystemClock.sleep(200);
            }
            return null;

        }

        //步骤3:定义收到pushProgress()触发后,在UI主线程执行的内容,在本例,将item加入list中。方法中的参数为范式方式,实质为数组,由于我们只传递了item一个String,要获取,为values[0]
        protected void onProgressUpdate(String... values/*参数2*/) {
            printInfo("onProgressUpdate  get param " + values[0]);
            ((ArrayAdapter<String>)getListAdapter()).add(values[0]);

        }
       
        //步骤4:定义后台进程执行完后的处理,本例,采用Toast

        protected void onPostExecute(Void result/*参数3*/) {
            printInfo("onPostExecute");
            Toast.makeText(Chapter15Test3.this, "Done!", Toast.LENGTH_SHORT).show();
        }          
    }    
}

我们根据printInfo跟踪各部分代码在哪里执行:doInBackground在后台线程执行,onProgressUpdate()和onPostExecute()在UI主线程执行。main就是UI主线程,而AsyncTask #1为后台线程,名字不一样。

 

以上转自:http://blog.csdn.net/flowingflying/article/details/6412667

如果不采用AsynTask,那么对于网络访问等耗时操作中,需要重启线程执行,当然要注意到线程同步问题。
public byte[] requestGet(String uri) { 
uri = urlheader + mUrl + uri;
byte[] strRet;
try {
HttpParams httpParameters = getHttpParams();
DefaultHttpClient httpclient = new DefaultHttpClient(httpParameters);
if (mCookieStore != null) {
httpclient.setCookieStore(mCookieStore);// 设置COOKIE
}
HttpResponse response;
HttpGet httpget = new HttpGet(uri);
response = httpclient.execute(httpget);
if (response.getStatusLine().getStatusCode() == 200) {

HttpEntity entity = response.getEntity();
strRet = EntityUtils.toByteArray(entity);
mCookieStore = httpclient.getCookieStore();// 更新本地存储的COOKIE
return strRet;
} else {
HttpEntity entity = response.getEntity();
Log.i("lwq", uri + ":" + response.getStatusLine().toString()
+ EntityUtils.toString(entity));
strRet = "null".getBytes();
return strRet;
}
} catch (Exception e) {
strRet = "null".getBytes();
e.printStackTrace();
}
return "null".getBytes();
}

另是一种需要重启线程,注意线程同步的方法:

byte[] strRet ;
private Object mLock; 
mLock = new Object(); 
public byte[] requestGet(String uri) {
uri = urlheader + mUrl + uri;
 
try {
HttpParams httpParameters = getHttpParams();

final DefaultHttpClient httpclient = new DefaultHttpClient(httpParameters);

if (mCookieStore != null) {
httpclient.setCookieStore(mCookieStore);// 设置COOKIE
}

final HttpGet httpget = new HttpGet(uri);
if (Config.DeBug) {
Log.i("permission", "start" + uri);
}

new Thread(){
public void run(){
//  保证主线程先运行
try
{
Thread.sleep(600);
} catch (InterruptedException e1)
{
// TODO Auto-generated catch block
e1.printStackTrace();

synchronized (mLock) {
try
{  
HttpResponse response = httpclient.execute(httpget);

if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
strRet = EntityUtils.toByteArray(entity);
if (strRet.length < 4) 
{
strRet = "null".getBytes();
}
mCookieStore = httpclient.getCookieStore();// 更新本地存储的COOKIE
}
else {
strRet = "null".getBytes();
// return strRet; 
}
} catch(SocketTimeoutException e){

e.printStackTrace();
strRet = "null".getBytes();
}catch (IOException e)
{
strRet = "null".getBytes();
}catch (Exception e) {
strRet = "null".getBytes();
}finally{

mLock.notify();

}
// Thread.yield();
}
}
}.start();


if (Config.DeBug) {
Log.i("permission", "end" + uri); 
}

synchronized (mLock) {
try {
mLock.wait();
//mLock.wait(10000);
} catch (InterruptedException e) {
}
return  strRet;
}  
} catch (Exception e) {

strRet = "null".getBytes();
e.printStackTrace(); 

}

return "null".getBytes();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值