最近看到谷歌官网上关于提升画面加载的教程,对于XML文件的认识又多了一些。

1.layout的深度不能太大,不然会严重影响加载界面的速度,能够平行布局就尽量平行布局。

2.利用include和merge标签来进行界面的复用。

3.使用ViewStub来自主决定什么时候加载。一个ViewStub包含有它自己的inflatedid以及layout,但是它平时是不会主动加载的,只有当需要时,自己调用inflate方法才会加载该界面。这样就可以让界面初始化时忽略该View从而提升速度。

4.使用另外的线程来处理可能会耗时比较多的操作。例如AsyncTask。

5.使用ViewHolder来存储已经加载好的View。先创建一个ViewHolder类,然后将加载好的View资源存放到里面,下次使用时就可以直接找到,而不用继续使用findViewById方法。

这五种方法里面,曾经在壁纸程序里接触过AsyncTask,但那时候并没有弄懂AsyncTask的工作原理,结合网上前辈的代码,现在总算大概弄明白了。写了一个简单的访问网络的demo,一个EditView,一个Button,一个TextView。代码如下:

package com.example.asynctaskex;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

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.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener{
	private EditText url;
	private TextView message;
	private Button button;
	private void log(String s){
		Log.i("bruce",s);
	}
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        url = (EditText)findViewById(R.id.etx);
        message = (TextView)findViewById(R.id.textView1);
        button = (Button)findViewById(R.id.btn);
        button.setOnClickListener(this);
    }

	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		connect();
	}
    
	public void connect(){
		PageTask pageTask = new PageTask(this);
		//通过AsyncTask来处理输入的网址。
		pageTask.execute("http://"+url.getText().toString());
	}
	
	class PageTask extends AsyncTask<String, Integer, String>{
		/*
		 * AsyncTask(arg1,arg2,arg3)其中arg1就是输入的网址,类型为String。arg2是中间参数,
		 * 用来实现ProgressBar的更新。arg3是doInBackground方法处理的结果,也是要传入最后调用方法
		 * onPostExecute(String s)的参数。AsyncTask必需实现两个方法doInBackground和onPostExecute
		 * 一个是对输入的内容进行处理,一个是对处理的结果进行显示。
		 */
		ProgressDialog dialog;
		public PageTask(Context contex){
			/*
			 * 构造函数,参数为Context。在构造的时候就定义好一个要用到的ProgressDialog,用于处理过程中
			 * 显示处理进度。
			 */
			dialog = new ProgressDialog(contex, 0);
			dialog.setButton("cancel", new DialogInterface.OnClickListener() {
				//在ProgressDialog中添加一个退出按钮。
				@Override
				public void onClick(DialogInterface dialog, int which) {
					// TODO Auto-generated method stub
					dialog.cancel();
				}
			});
			/*
			 * 这里退出按钮进行了分步,单击按钮时只是cancel,当cancel方法调用时setOnCancelListener
			 * 随之被触发,可以在这里加一些其他的处理。这里是直接关掉整个Activity,正常情况下,不用复写,
			 * 直接cancel退出diaglog就好
			 */
		
			dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
				//ProgressDialog的cancel调用时会运行该方法。
				@Override
				public void onCancel(DialogInterface dialog) {
					// TODO Auto-generated method stub
					finish();
				}
			});
			dialog.setCancelable(true);
			dialog.setMax(100);
			dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			dialog.show();
		}
		/*
		 * pageTask.execute(),这个方法调用的时候就会蹦到onPreExecute()去,onPreExecute()之后
		 * 就是doInBackground了。参数中的String... params表示该参数的个数是可变的,可以传入多个,但
		 * 必需都是String类型的。多个参数会以数组的形式存在params[]中。这里默认的第一个参数就是params[0]
		 *
		 */
		@Override
		protected String doInBackground(String... params) {
			// TODO Auto-generated method stub
			//获得当前的网络状态
			ConnectivityManager conManager = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo networkInfo = conManager.getActiveNetworkInfo();
			log("networkInfo"+networkInfo);
			log("networkInfo.isConnected()"+networkInfo.isConnected());
			try{
				if(networkInfo != null && networkInfo.isConnected()){
					HttpClient client = new DefaultHttpClient();
					HttpGet get = new HttpGet(params[0]);
					HttpResponse response = client.execute(get);
					HttpEntity entity = response.getEntity();
					long length = entity.getContentLength();
					InputStream stream = entity.getContent();
					String s = null;
					if(stream != null){
						ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
						byte[] buf = new byte[128];
						int ch = -1;
						int count = 0;
						while((ch = stream.read(buf)) != -1){
							outputStream.write(buf, 0, ch);
							count += ch;
							if(length > 0){
								publishProgress((int)(count/length)*100);
								//publishProgress方法执行后就会执行 onProgressUpdate方法
							}
						}
						s = new String(outputStream.toByteArray());
					}
					return s;
				}else{
					return null;
				}
			}catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
			return null;
		}
		@Override
		protected void onPostExecute(String result) {
			// TODO Auto-generated method stub
			message.setText(result);
			dialog.dismiss();
		}
		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			message.setText("task started");
		}
		@Override
		protected void onProgressUpdate(Integer... values) {
			// TODO Auto-generated method stub
			message.setText(""+values[0]);
			dialog.setProgress(values[0]);
		}
		
		
	}
}