好郁闷,写了好长时间,不小心按到舍弃。。。。。。。
android中的多线程编程可以说是式采用了java当中的模式,但是java所提供的技术有时候满足不了android的需求。在android当中,有些操作需要在子线程当中完成,比如网络编程,而有些操作需要在主线程挡住完成,比如UI更新。那么问题来了,我们要怎么把网络上获取的数据传送到子线程当中来进行UI更新呢。什么?static?别闹了,会死人的。那么这里android给我么提供了一种消息的传送机制,来满足我们这些需求。简单的说,android给我们提供了一个消息队列,让我们可以在子线程当中把网络上获取的数据送到消息队列当中去,而这个消息队列的目的地,可以是主线程当中,所以我们可以在主线程当中来接受这些数据,来进行只能在主线程当中完成的数据操作。
第一种方式,Thread+Handler:
public class MainActivity extends AppCompatActivity {
Button button1, button2;
TextView textView1;
ImageView imageView1;
//这里我喜欢static,可以再其他类中用类名调用
static MyHandler myHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView1 = (TextView) findViewById(R.id.textview1);
imageView1 = (ImageView) findViewById(R.id.imageview1);
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
//这步别忘了,必须放在主线程当中,最好放在setContentView后面
myHandler = new MyHandler();
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new MyRunnable()).start();
}
});
}
//在子线程当中执行的任务
class MyRunnable implements Runnable {
@Override
public void run() {
//个人喜欢这种方式创建Message对象,不绑定handler,比较灵活
Message message = Message.obtain();
//分别加载数据
message.arg1 = 1;
message.arg2 = 2;
message.obj = "obj";
message.what = 3;
message.setData(new Bundle());
//这能体现灵活,可以使用不同的多个handler来发送同一个message
myHandler.sendMessage(message);
}
}
//在主线程当中执行的任务
class MyHandler extends Handler {
//在activity当中都有默认的looper对象来绑定handler
public MyHandler() {
super();
}
//在有的类当中,我们需要自己创建一个Looper looper = Looper.myLooper();
public MyHandler(Looper looper) {
super(looper);
}
//在主线程当中处理的事务
@Override
public void handleMessage(Message msg) {
//这里可以把所有的数据都取出来,然后进行数据操作,这里只取了一个
textView1.setText(msg.obj.toString());
}
}
}
第二种方式,AsyncTask异步任务,其实这个方法的内部实现也是Thread+Handler,只不过是把他们封装起来了。这点就像是IntentServer和Server的区别。当面向对象嘛,优点之一就是能消除很多重复的代码,方便实用嘛。
这里写了一个下载网络图片的代码功能:
public class MainActivity extends AppCompat的Activity {
Button button1, button2;
TextView textView1;
ImageView imageView1;
static String PATH = "http://e.hiphotos.baidu.com/image/pic/item/dcc451da81cb39db026e7657d2160924ab183000.jpg";
ProgressDialog progressDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView1 = (TextView) findViewById(R.id.textview1);
imageView1 = (ImageView) findViewById(R.id.imageview1);
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//注意这里的执行方法,只有一个参数
new MyTask().execute(PATH);
}
});
}
/**
* 声明一个类继承AsyncTask并标注三个参数
* 1.第一个参数表示要执行的任务通常是网络的途径
* 2.第二个参数表示进度的刻度
* 3.第三个参数表示任务执行的返回结果
*/
class MyTask extends AsyncTask<String, Integer, Bitmap> {
//在mainThread当中,表示任务执行之前的操作
@Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(MainActivity.this);
progressDialog.setTitle("提示信息");
progressDialog.setMessage("正在下载中...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.show();
}
//在子线程当中,主要完成耗时操作
@Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap = null;
InputStream inputStream = null;
//这里就不用null了
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try {
URL url = new URL(PATH);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setDoInput(true);
httpURLConnection.setConnectTimeout(3000);
int responseCode = httpURLConnection.getResponseCode();
if (responseCode == 200)
inputStream = httpURLConnection.getInputStream();
if (inputStream != null) {
byte[] bytes = new byte[1024];
int len = -1;
//先获取文件的总长度
long file_len = httpURLConnection.getContentLength();
//当前已下载长度
int current_len = 0;
while ((len = inputStream.read(bytes)) != -1) {
current_len += len;
int value = (int) ((current_len / (float) file_len) * 100);
//把刻度发布到onProgressUpdate方法当中
publishProgress(value);
//将读入的数据再次写入到字节流当中,这里的第三个参数不能是bytes.length
byteArrayOutputStream.write(bytes, 0, len);
}
}
byte[] result = byteArrayOutputStream.toByteArray();
bitmap = BitmapFactory.decodeByteArray(result, 0, result.length);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (inputStream != null)
inputStream.close();
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return bitmap;
}
//在mainThread当中,主要用于更新Bar的progress
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressDialog.setProgress(values[0]);
}
//在mainThread当中,主要更新UI操作
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
progressDialog.dismiss();
imageView1.setImageBitmap(bitmap);
}
}
}