Android的线程通信和异步任务:使用三级缓存加载图片,自动增值练习,使用和不使用Handler进行异步任务

三级缓存加载图片

步骤:
	1. 搭建服务器端
	2. 界面布局
		整体 : ListView+提示视图
		Item : LinearLayout
	3. 动态显示列表
		使用Handler+Thread处理联网请求, 得到json数据, 解析成List<ShopInfo>
		使用BaseAdapter显示文本列表
		根据url, 异步请求显示图片(使用三级缓存)
	
	4. 动态显示列表中的图片
		--->Bitmap--->手机本地的图片文件--->服务器端的图片文件
	1). 图片的三级缓存
		一级缓存: 内存缓存, 缓存的是bitmap对象, 用Map<String, Bitmap>结构保存, key是url
		二级缓存: 本地(sd卡)缓存, 缓存的是图片文件,  /storage/sdcard/Android/data/packageName/files/图片文件名(xxx.jpg) 
		三级缓存: 远程服务器缓存, 缓存的是图片文件, 远程服务器上的应用中
	2). 如何使用三级缓存?  -----如何根据图片的url动态显示图片?    
		String iamgePath = http://192.168.80.1:8080//L05_Web/images/f10.jpg和ImageView对象
		1). 根据url从一级缓存中取对应的bitmap对象
			如果有, 显示(结束)
			如果没有, 进入2)
		2). 从二级缓存中查找: 得到文件名并在sd卡的缓存目录下加载对应的图片得到Bitmap对象
			如果有: 显示, 缓存到一级缓存中(结束)
			如果没有, 进入3)
		3). 显示代表提示正在加载的图片, 启动分线程联网请求得到Bitmap对象
				如果没有: 显示提示错误的图片(结束)
				如果有: 
					显示
					缓存到一级缓存
					缓存到二级缓存
	3). 在ListView使用图片三级缓存会存在图片闪动的bug
		1). 原因
			converView被复用了
		2). 解决
			a. 每次getView()都将图片的url保存到ImageView上: imageView.setTag(imagePath)
			b. 在分线程准备请求服务器加载图片之前, 比较准备加载图片的url与ImageView中保存的最新图片的url是同一个, 
				如果不是同一个, 当前加载图片的任务不应该再执行
				如果相同, 继续执行加载远程图片
			c. 在主线程准备显示图片之前, 比较加载到图片的url与ImageView中保存的最新图片的url是同一个
				如果不是同一个, 不需要显示此图片
				如果相同, 显示图片
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <ListView
        android:id="@+id/lv_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

    <LinearLayout
        android:id="@+id/ll_main_loading"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" 
        android:gravity="center"
        android:visibility="gone">

        <ProgressBar
            style="?android:attr/progressBarStyleLarge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="正在加载中..." />
    </LinearLayout>
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/iv_item_icon"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:src="@drawable/ic_launcher"/>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" 
        android:gravity="center_vertical"
        android:layout_marginLeft="10dp">

        <TextView
            android:id="@+id/tv_item_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="名称" 
            android:textSize="18sp"/>
        
        <TextView
            android:id="@+id/tv_item_price"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="内容" 
            android:textSize="18sp"/>
    </LinearLayout>
</LinearLayout>
package com.jane.threeCache;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.atguigu.app05_handler.R;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

public class MainActivity extends Activity
{

	protected static final int WHAT_REQUEST_SUCCESS = 1;
	protected static final int WHAT_REQUEST_ERROR = 2;
	private ListView lv_main;
	private LinearLayout ll_main_loading;
	private List<ShopInfo> data;
	private ShopInfoAdapter adapter;
	private Handler handler = new Handler()
	{
		public void handleMessage(android.os.Message msg)
		{
			switch (msg.what)
			{
			case WHAT_REQUEST_SUCCESS:
				ll_main_loading.setVisibility(View.GONE);
				// 显示列表
				lv_main.setAdapter(adapter);
				break;
			case WHAT_REQUEST_ERROR:
				ll_main_loading.setVisibility(View.GONE);
				Toast.makeText(MainActivity.this, "加载数据失败", 1).show();
				break;

			default:
				break;
			}
		}
	};
	@Override
	protected void onCreate(Bundle savedInstanceState) 
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		lv_main = (ListView) findViewById(R.id.lv_main);
		ll_main_loading = (LinearLayout) findViewById(R.id.ll_main_loading);
		adapter = new ShopInfoAdapter();
		
		//1. 主线程, 显示提示视图
		ll_main_loading.setVisibility(View.VISIBLE);
		//2. 分线程, 联网请求
		//启动分线程请求服务器动态加载数据并显示
		new Thread()
		{
			public void run() 
			{
				//联网请求得到jsonString
				try 
				{
					String jsonString = requestJson();
					//解析成List<ShopInfo>
					data = new Gson().fromJson(jsonString, new TypeToken<List<ShopInfo>>(){}.getType());
					//3. 主线程, 更新界面
					handler.sendEmptyMessage(WHAT_REQUEST_SUCCESS);//发请求成功的消息
				} catch (Exception e) 
				{
					e.printStackTrace();
					handler.sendEmptyMessage(WHAT_REQUEST_ERROR);//发送请求失败的消息
				}
			}
		}.start();
	}
	
	/**
	 * 联网请求得到jsonString
	 * @return
	 * @throws Exception 
	 */
	private String requestJson() throws Exception 
	{
		String result = null;
		String path = "http://192.168.80.1:8080/L05_Web/ShopInfoListServlet";
		//1. 得到连接对象
		URL url = new URL(path);
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		//2. 设置
		connection.setConnectTimeout(5000);
		connection.setReadTimeout(5000);
		//连接
		connection.connect();
		//发请求并读取服务器返回的数据
		int responseCode = connection.getResponseCode();
		if (responseCode == 200)
		{
			InputStream is = connection.getInputStream();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			byte[] buffer = new byte[1024];
			int len = -1;
			while ((len = is.read(buffer)) != -1)
			{
				baos.write(buffer, 0, len);
			}
			baos.close();
			is.close();
			connection.disconnect();

			result = baos.toString();
		} else
		{
			// 也可以抛出运行时异常
		}
		return result;
	}

	class ShopInfoAdapter extends BaseAdapter
	{
		private ImageLoader imageLoader;
		public ShopInfoAdapter()
		{
			imageLoader = new ImageLoader(MainActivity.this,R.drawable.loading, R.drawable.error);
		}

		@Override
		public int getCount()
		{
			return data.size();
		}

		@Override
		public Object getItem(int position)
		{
			return data.get(position);
		}

		@Override
		public long getItemId(int position)
		{
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent)
		{
			if (convertView == null)
			{
				convertView = View.inflate(MainActivity.this,R.layout.item_main, null);
			}
			// 得到当前行的数据对象
			ShopInfo shopInfo = data.get(position);
			// 得到当前行的子View
			TextView nameTV = (TextView) convertView.findViewById(R.id.tv_item_name);
			TextView priceTV = (TextView) convertView.findViewById(R.id.tv_item_price);
			ImageView imageView = (ImageView) convertView.findViewById(R.id.iv_item_icon);
			// 设置数据
			nameTV.setText(shopInfo.getName());
			priceTV.setText(shopInfo.getPrice() + "元");
			String imagePath = shopInfo.getImagePath();
			// 根据图片路径启动分线程动态请求服务加载图片并显示
			imageLoader.loadImage(imagePath, imageView);
			return convertView;
		}
	}
}
package com.jane.threeCache;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;

/**
 * 用于加载图片并显示的类
 */
/*
	String iamgePath = http://192.168.80.1:8080//L05_Web/images/f10.jpg和ImageView对象
	1). 根据url从一级缓存中取对应的bitmap对象
		如果有, 显示(结束)
		如果没有, 进入2)
	2). 从二级缓存中查找: 得到文件名并在sd卡的缓存目录下加载对应的图片得到Bitmap对象
		如果有: 显示, 缓存到一级缓存中(结束)
		如果没有, 进入3)
	3). 显示代表提示正在加载的图片, 启动分线程联网请求得到Bitmap对象
			如果没有: 显示提示错误的图片(结束)
			如果有: 
				显示
				缓存到一级缓存
				缓存到二级缓存
 */
public class ImageLoader 
{
	private Context context;
	private int loadingImageRes;
	private int errorImageRes;

	public ImageLoader(Context context, int loadingImageRes, int errorImageRes) 
	{
		super();
		this.context = context;
		this.loadingImageRes = loadingImageRes;
		this.errorImageRes = errorImageRes;
	}

	//用于缓存bitmap的容器对象
	private Map<String, Bitmap> cacheMap = new HashMap<String, Bitmap>();
	
	/**
	 * 加载图片并显示
	 * @param imagePath
	 * @param imageView
	 */
	public void loadImage(String imagePath, ImageView imageView) 
	{
		//将需要显示的图片url保存到视图上
		imageView.setTag(imagePath);
		
		/*
		 1). 根据url从一级缓存中取对应的bitmap对象
			如果有, 显示(结束)
			如果没有, 进入2)
		 */
		Bitmap bitmap = getFromFirstCache(imagePath);
		if(bitmap!=null) 
		{
			imageView.setImageBitmap(bitmap);
			return;
		}
		/*
		2). 从二级缓存中查找: 得到文件名并在sd卡的缓存目录下加载对应的图片得到Bitmap对象
				如果有: 显示, 缓存到一级缓存中(结束)
				如果没有, 进入3)
			
			/storage/sdcard/Android/data/packageName/files/图片文件名(xxx.jpg)
		 */
		bitmap = getFromSecondCache(imagePath);
		if(bitmap!=null) 
		{
			imageView.setImageBitmap(bitmap);
			cacheMap.put(imagePath, bitmap);
			return;
		}
		
		/*
		 3). 显示代表提示正在加载的图片, 启动分线程联网请求得到Bitmap对象
			如果没有: 显示提示错误的图片(结束)
			如果有: 
				缓存到一级缓存(分线程)
				缓存到二级缓存(分线程)
				显示(主线程)
				
		 */
		
		loadBitmapFromThirdCache(imagePath, imageView);
	}

	/**
	 * 根据图片url从三级缓存中取对应的bitmap对象并显示
	 * @param imagePath
	 * @param imageView
	 * AsyncTask
	 * loadBitmapFromThirdCache("../b.jpg", imageView)
	 * loadBitmapFromThirdCache("../f.jpg", imageView)--->imageView.setTag("../f.jpg")
	 */
	private void loadBitmapFromThirdCache(final String imagePath, final ImageView imageView) 
	{
		new AsyncTask<Void, Void, Bitmap>() 
		{
			protected void onPreExecute() 
			{
				imageView.setImageResource(loadingImageRes);
			}
			
			//联网请求得到bitmap对象
			@Override
			protected Bitmap doInBackground(Void... params) 
			{
				//在分线程执行, 可能需要等待一定时间才会执行
				//在等待的过程中imageView中的tag值就有可能改变了
				//如果改变了, 就不应该再去加载图片(此图片此时不需要显示)
				
				Bitmap bitmap = null;
				try 
				{
					
					//在准备请求服务器图片之前, 判断是否需要加载
					String newImagePath = (String) imageView.getTag();
					if(newImagePath!=imagePath) {//视图已经被复用了
						return null;
					}
					
					//得到连接
					URL url = new URL(imagePath);
					HttpURLConnection connection = (HttpURLConnection) url.openConnection();
					//设置
					connection.setConnectTimeout(5000);
					connection.setReadTimeout(5000);
					//连接
					connection.connect();
					//发请求读取返回的数据并封装为bitmap
					int responseCode = connection.getResponseCode();
					if(responseCode==200) 
					{
						InputStream is = connection.getInputStream();//图片文件流
						//将is封装为bitmap
						bitmap = BitmapFactory.decodeStream(is);
						is.close();
						
						if(bitmap!=null) 
						{
							//缓存到一级缓存(分线程)
							cacheMap.put(imagePath, bitmap);
							//缓存到二级缓存(分线程)
							// /storage/sdcard/Android/data/packageName/files/
							String filesPath = context.getExternalFilesDir(null).getAbsolutePath();
							// http://192.168.80.1:8080//L05_Web/images/f10.jpg
							String fileName = imagePath.substring(imagePath.lastIndexOf("/")+1);//  f10.jpg
							String filePath = filesPath+"/"+fileName;
							bitmap.compress(CompressFormat.JPEG, 100, new FileOutputStream(filePath));
						}
					}
					connection.disconnect();
				} catch (Exception e) 
				{
					e.printStackTrace();
				}
				return bitmap;
			}
			
			protected void onPostExecute(Bitmap bitmap) 
			{
				//从联网请求图片到得到图片对象需要一定的时间, 视图可能被复用了,不需要显示
				//在主线程准备显示图片之前, 需要判断是否需要显示
				String newImagePath = (String) imageView.getTag();
				if(newImagePath!=imagePath) 
				{
					//视图已经被复用了
					return;
				}
						
				//如果没有: 显示提示错误的图片(结束)
				if(bitmap==null) 
				{
					imageView.setImageResource(errorImageRes);
				} else 
				{
					//如果有, 显示
					imageView.setImageBitmap(bitmap);
				}
			}
		}.execute();
	}

	/**
	 * 根据图片url从二级缓存中取对应的bitmap对象
	 * @param imagePath
	 * @return
	 */
	private Bitmap getFromSecondCache(String imagePath) 
	{
		// /storage/sdcard/Android/data/packageName/files/
		String filesPath = context.getExternalFilesDir(null).getAbsolutePath();
		// http://192.168.80.1:8080//L05_Web/images/f10.jpg
		String fileName = imagePath.substring(imagePath.lastIndexOf("/")+1);//  f10.jpg
		String filePath = filesPath+"/"+fileName;
		
		return BitmapFactory.decodeFile(filePath);
	}

	/**
	 * 根据图片url从一级缓存中取对应的bitmap对象
	 * @param imagePath
	 * @return
	 */
	private Bitmap getFromFirstCache(String imagePath)
	{
		return cacheMap.get(imagePath);
	}
}
package com.jane.threeCache;

public class ShopInfo
{

	private int id; // 一定要与json对象字符串中的key的名称要一致
	private String name;
	private double price;
	private String imagePath;

	public ShopInfo(int id, String name, double price, String imagePath)
	{
		super();
		this.id = id;
		this.name = name;
		this.price = price;
		this.imagePath = imagePath;
	}

	public ShopInfo()
	{
		super();
	}

	public int getId()
	{
		return id;
	}

	public void setId(int id)
	{
		this.id = id;
	}

	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public double getPrice()
	{
		return price;
	}

	public void setPrice(double price)
	{
		this.price = price;
	}

	public String getImagePath()
	{
		return imagePath;
	}

	public void setImagePath(String imagePath)
	{
		this.imagePath = imagePath;
	}

	@Override
	public String toString()
	{
		return "ShopInfo [id=" + id + ", name=" + name + ", price=" + price
				+ ", imagePath=" + imagePath + "]";
	}

}

自动增值练习

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv_demo_number"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="10"
        android:textColor="#ff0000" 
        android:textSize="20sp"/>

    <Button
        android:id="@+id/btn_demo_increase"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="自动增加" />

    <Button
        android:id="@+id/btn_demo_decrease"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="自动减少" />

    <Button
        android:id="@+id/btn_demo_pause"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="暂停" 
        android:enabled="false"/>

</LinearLayout>
package com.example.myhandler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

/**
 * 使用Handler:
1. 初始时
     显示10,可以通过点击按钮改变其值
2. 点击“自动增加”
     每隔1S上面的文本数值增加1,但最大显示20并作出提示
3. 点击“自动减少”
     每隔1S上面的文本数值减少1,但最小显示1并作出提示
4. 点击“暂停”
   上面的数值文本不再变化

写的步骤:
1. 手动增加/减少
2. 自动增加/减少
3. 限制数字的最大和最小值 [1,20]
4. 限制Button可操作性
 */
public class HandlerDemoActivity extends Activity implements OnClickListener
{

	private static final int WHAT_INCREASE = 1;
	private static final int WHAT_DECREASE = 2;

	private TextView tv_demo_number;
	private Button btn_demo_increase;
	private Button btn_demo_decrease;
	private Button btn_demo_pause;

	private Handler handler = new Handler()
	{
		public void handleMessage(android.os.Message msg)
		{
			// 得到当前显示的数值
			int number = Integer.parseInt(tv_demo_number.getText().toString());
			switch (msg.what)
			{
			case WHAT_INCREASE:
				// 限制number<=20
				if (number == 20)
				{
					// 设置暂停不能操作
					btn_demo_pause.setEnabled(false);
					Toast.makeText(HandlerDemoActivity.this, "已经达到最大值", 0)
							.show();
					return;
				}

				number++;
				tv_demo_number.setText(number + "");
				// 发送增加的延迟消息
				handler.sendEmptyMessageDelayed(WHAT_INCREASE, 1000);
				break;
			case WHAT_DECREASE:
				// 限制number>=1
				if (number == 1)
				{
					// 设置暂停不能操作
					btn_demo_pause.setEnabled(false);
					Toast.makeText(HandlerDemoActivity.this, "已经达到最小值", 0)
							.show();
					return;
				}
				number--;
				tv_demo_number.setText(number + "");
				// 发送减少的延迟消息
				handler.sendEmptyMessageDelayed(WHAT_DECREASE, 1000);
				break;
			default:
				break;
			}
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_handler_demo);
		init();
	}

	private void init()
	{
		tv_demo_number = (TextView) findViewById(R.id.tv_demo_number);
		btn_demo_increase = (Button) findViewById(R.id.btn_demo_increase);
		btn_demo_decrease = (Button) findViewById(R.id.btn_demo_decrease);
		btn_demo_pause = (Button) findViewById(R.id.btn_demo_pause);

		btn_demo_increase.setOnClickListener(this);
		btn_demo_decrease.setOnClickListener(this);
		btn_demo_pause.setOnClickListener(this);
	}

	@Override
	public void onClick(View v)
	{
		if (v == btn_demo_increase)
		{// 自动增加 what =1
			// 限制Button可操作性
			btn_demo_increase.setEnabled(false);
			btn_demo_decrease.setEnabled(true);
			btn_demo_pause.setEnabled(true);

			// 停止减少(移除未处理的减少的消息)
			handler.removeMessages(WHAT_DECREASE);
			// 发消息(增加)
			handler.sendEmptyMessage(WHAT_INCREASE);
		} else if (v == btn_demo_decrease)
		{// 自动减少 what=2
			// 限制Button可操作性
			btn_demo_increase.setEnabled(true);
			btn_demo_decrease.setEnabled(false);
			btn_demo_pause.setEnabled(true);

			// 停止增加(移除未处理的增加的消息)
			handler.removeMessages(WHAT_INCREASE);

			// 发消息(减少)
			handler.sendEmptyMessage(WHAT_DECREASE);
		} else if (v == btn_demo_pause)
		{// 暂停

			// 限制Button可操作性
			btn_demo_increase.setEnabled(true);
			btn_demo_decrease.setEnabled(true);
			btn_demo_pause.setEnabled(false);

			// 停止增加/减少(移除未处理的减少/增加的消息)
			handler.removeMessages(WHAT_INCREASE);
			handler.removeMessages(WHAT_DECREASE);
		}
	}
}

使用和不使用Handler进行异步任务

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <ProgressBar
        android:id="@+id/pb_handler1_loading"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" 
        android:visibility="invisible"/>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="getSubmit1"
        android:text="GET Submit" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="getSubmit2"
        android:text="GET Submit2" />

    <EditText
        android:id="@+id/et_handler1_result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="显示结果" >
    </EditText>
</LinearLayout>
package com.example.myhandler;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.EditText;
import android.widget.ProgressBar;


/**
 *  点击GET请求获取: 显示提示正在加载的进度条, 分线程请求网络
	得据后,显示到输入框中, 同时隐藏进度条
 * 
 * 测试Handler的基本使用

	使用Handler的一般步骤
		1. 创建Handler成员变量对象, 并重写其handleMessage()
		2. 在分/主线程创建Message对象
		3. 使用handler对象发送Message
		4. 在handleMessage()中处理消息
 */
public class HandlerTestActivity extends Activity
{
	private ProgressBar pb_handler1_loading;
	private EditText et_handler1_result;
	
	// 1. 创建Handler成员变量对象, 并重写其handleMessage()
	private Handler handler = new Handler()
	{
		// 在主线程执行
		public void handleMessage(android.os.Message msg)
		{
			if (msg.what == 1)
			{
				// 4. 在handleMessage()中处理消息
				String result = (String) msg.obj;
				et_handler1_result.setText(result);
				pb_handler1_loading.setVisibility(View.INVISIBLE);
			}
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_handler_test);

		pb_handler1_loading = (ProgressBar) findViewById(R.id.pb_handler1_loading);
		et_handler1_result = (EditText) findViewById(R.id.et_handler1_result);
	}

	/*
	 1. 主线程, 显示提示视图(ProgressDialog/ProgressBar)
     2. 分线程, 联网请求, 并得到响应数据
     3. 主线程, 显示数据/隐藏提示视图
	 */
	public void getSubmit1(View v)
	{
		// 1. 主线程, 显示提示视图(ProgressDialog/ProgressBar)
		pb_handler1_loading.setVisibility(View.VISIBLE);
		// 2. 分线程, 联网请求, 并得到响应数据
		new Thread()
		{
			public void run()
			{
				String path = "http://192.168.80.1:8080/Android/index.jsp?username=jane&age=18";
				try
				{
					final String result = requestToString(path);

					// 3. 主线程, 显示数据
					runOnUiThread(new Runnable()
					{
						@Override
						public void run()
						{
							et_handler1_result.setText(result);
							pb_handler1_loading.setVisibility(View.INVISIBLE);
						}
					});
				} catch (Exception e)
				{
					e.printStackTrace();
				}
			}
		}.start();
	}
	
	public void getSubmit2(View v)
	{
		// 1). 主线程, 显示提示视图(ProgressDialog/ProgressBar)
		pb_handler1_loading.setVisibility(View.VISIBLE);
		// 2). 分线程, 联网请求, 并得到响应数据
		new Thread()
		{
			public void run()
			{
				String path = "http://192.168.80.1:8080/Android/index.jsp?username=jane&age=18";
				try
				{
					String result = requestToString(path);

					// 3). 主线程, 显示数据
					// 2. 在分/主线程创建Message对象
					Message message = Message.obtain();
					message.what = 1;// 标识
					message.obj = result;
					// 3. 使用handler对象发送Message
					handler.sendMessage(message);
				} catch (Exception e)
				{
					e.printStackTrace();
				}
			}
		}.start();
	}
	
	/**
	 * 请求服务器端, 得到返回的结果字符串
	 * @param path  : http://192.168.80.1:8080/Android/index.jsp?username=jane&age=18
	 * @return
	 * @throws Exception
	 */
	public String requestToString(String path) throws Exception 
	{
		URL url = new URL(path);
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		connection.setConnectTimeout(5000);
		connection.setReadTimeout(5000);
		connection.connect();
		InputStream is = connection.getInputStream();
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = -1;
		while ((len = is.read(buffer)) != -1)
		{
			baos.write(buffer, 0, len);
		}
		baos.close();
		is.close();
		String result = baos.toString();
		connection.disconnect();
		return result;
	}
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ReflectMirroring

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值