虽然今天礼拜六还在加班,但是在等接口,所以还是有很多时间来自己学点东西的,所以就接着昨天的来。今天继续学的是不通过主线程来更新主线程的界面的问题。
昨天是用的开启线程调用Handler来更新线程,那个效果用的方面比较广阔,那么我们还有几种方法将耗时的代码剥离出来不在主线程里面执行,然后通过各种方法来更新UIThread .今天学到的是利用AsynTask来更新主界面的空间。
然后我们先来说说AsynTask:
AsynTask:Asynchronous Task(异步任务)
使用过AsyncTask 的同学都知道一个异步加载数据最少要重写以下这两个方法:
- doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。
- onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回
有必要的话你还得重写以下这三个方法,但不是必须的:
- onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
- onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
- onCancelled() 用户调用取消时,要做的操作
使用AsyncTask类,以下是几条必须遵守的准则:
- Task的实例必须在UI thread中创建;
- execute方法必须在UI thread中调用;
- 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
- 该task只能被执行一次,否则多次调用时将会出现异常;
好了继续以往风格,再说需求:
需求是在界面通过输入一个完整的网址然后通过点击按钮来访问网络,在访问的时候展示一个进度条,然后将得到的网页代码显示在主界面上。
然后上代码:TestAsynTaskActivity
package com.example.testandroid; import android.app.Activity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View.OnClickListener; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.ArrayList; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class TestAsynTaskActivity extends Activity implements OnClickListener { private TextView message; private Button open; private EditText url; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_asyn_task); message = (TextView) findViewById(R.id.show); url = (EditText) findViewById(R.id.url); open = (Button) findViewById(R.id.open); open.setOnClickListener(this); } private void connect() { PageTask task = new PageTask(this); task.execute(url.getText().toString()); } class PageTask extends AsyncTask<String, Integer, String> { // 可变长的输入参数,与AsyncTask.exucute()对应 ProgressDialog pdialog; public PageTask(Context context) { pdialog = new ProgressDialog(context, 0); pdialog.setButton("cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int i) { dialog.cancel();//这个方法过时了。 } }); pdialog.setOnCancelListener(new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) { finish(); } }); pdialog.setCancelable(true); pdialog.setMax(100); pdialog.setTitle("正在请求网络!"); pdialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); pdialog.show(); } @Override protected String doInBackground(String... params) { try { HttpClient client = new DefaultHttpClient(); // params[0]代表连接的url HttpGet get = new HttpGet(params[0]); HttpResponse response = client.execute(get); HttpEntity entity = response.getEntity(); long length = entity.getContentLength(); InputStream is = entity.getContent(); String s = null; if (is != null) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buf = new byte[128]; int ch = -1; int count = 0; while ((ch = is.read(buf)) != -1) { baos.write(buf, 0, ch); count += ch; if (length > 0) { // 如果知道响应的长度,调用publishProgress()更新进度 publishProgress((int) ((count / (float) length) * 100)); } // 让线程休眠100ms Thread.sleep(100); } s = new String(baos.toByteArray()); } // 返回结果 return s; } catch (Exception e) { e.printStackTrace(); } return null; } @Override protected void onCancelled() { super.onCancelled(); } @Override protected void onPostExecute(String result) { // 返回HTML页面的内容 message.setText(result); pdialog.dismiss(); } @Override protected void onPreExecute() { // 任务启动,可以在这里显示一个对话框,这里简单处理 message.setText("正在更新。。。"); } @Override protected void onProgressUpdate(Integer... values) { // 更新进度 System.out.println("" + values[0]); message.setText("" + values[0]); pdialog.setProgress(values[0]); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.open: connect(); break; default: break; } } }
下面是xml文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" > <TextView android:id="@+id/show" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="15dp" android:background="@drawable/shape1" android:hint="@string/tv_hint" /> <EditText android:id="@+id/url" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_below="@id/show" android:layout_marginLeft="15dp" android:layout_marginTop="15dp" android:background="@null" android:hint="在这里输入网址" /> <Button android:id="@+id/open" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/url" android:layout_marginLeft="15dp" android:layout_marginTop="15dp" android:background="@drawable/shape2" android:text="打开网页" android:textColor="#FFFFFF" android:textSize="20dp" /> </RelativeLayout> </ScrollView> </RelativeLayout>
最后,因为是要访问网络,我们要记得在manifest文件里面加入INTERNET权限。好啦简单的一个AsynTask的实现就完成了!
时间: 2024-10-22 07:05:57