最近在做Android客户端给Tomcat服务器传输文件,Android端要显示文件上传的进度,在界面显示。文件上传任务,是交给Service开启的子线程在做,每一步传输的进度,通过MainActivity.mHandler调用sendEmptyMessage通知MainActivity进行进度条更新。
上传文件的Service进度监听如下:
while((len = in.read(buf))!=-1){
curProgress += len;
sb.append(new String(buf,0,len));
progress = (float) ((curProgress/file.length())*100.0);
Message msg = Message.obtain();
Bundle bundle = new Bundle();
bundle.putFloat("UpProgress",50);
msg.setData(bundle);
MainActivity.mHandler.sendEmptyMessage(MainActivity.UP_PROGRESS);
}
MainActivity的mHandler处理如下:
mHandler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case UP_PROGRESS://上传进度
Bundle bundle2 = msg.getData();
float pro = bundle2.getFloat("UpProgress");
//更新进度条
upProgressBar.setProgress((int) pro);
builder.setContentTitle("正在上传")
.setSmallIcon(R.mipmap.ic_launcher);
builder.setContentText("已完成"+pro+"%");
builder.setProgress(100, (int) pro, false);
manager.notify(100, builder.build());
break;
}
}
};
调试运行,发现界面的进度条并没有更新。我折腾了半天,以为服务器接收有问题或Android端发送文件有问题,导致没有获得进度。奇怪的是,后来发现文件成功上传了,PC服务器指定目录已上传成功。我回过头想,究竟是哪的问题,之前使用类似于MainActivity的mHandler处理短暂界面更新的都没问题。
最后问题锁定在MainActivity.mHandler.sendEmptyMessage(MainActivity.UP_PROGRESS);方法上。因为之前用的都是sendMessage方法。
查找相关资料,都说sendEmptyMessage和sendMessage两者没区别,最后还是尝试了一番,把上传文件的Service进度监听更改为:
改用sendMessage就OK了。这倒也奇怪,看sendMessage和sendEmptyMessage的源码:while((len = in.read(buf))!=-1){ curProgress += len; sb.append(new String(buf,0,len)); progress = (float) ((curProgress/file.length())*100.0); Message msg = Message.obtain(); Bundle bundle = new Bundle(); bundle.putFloat("UpProgress",progress); msg.setData(bundle); msg.what = MainActivity.UP_PROGRESS; MainActivity.mHandler.sendMessage(msg); }
public final boolean sendMessage(Message msg){ return sendMessageDelayed(msg, 0); }
public final boolean sendEmptyMessage(int what){ return sendEmptyMessageDelayed(what, 0); }
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) { Message msg = Message.obtain(); msg.what = what; return sendMessageDelayed(msg, delayMillis); }
原来在sendEmptyMessageDelayed中就是构建了一个Message,然后把这个Message的what设置成sendEmptyMessage方法中的What参数即可。 然后,在主线程中,Looper类的
loop()通过 调用:msg.target.dispatchMessage(msg),调用Hanler类的dispatchMessage(Message msg)方法,从而在主线程中处理了这个Message。二者没什么区别,但在此执行,却也不解。
最后,关于使用Message的补充:
1.Message有public的默认构造方法,可以直接new Message();但是应该通过Message.obtain()来从消息池中获得空消息对象,以节省资源,这也是Google推荐的方式。
2.如果你的message只需要携带简单的int信息,请优先使用Message.arg1和Message.arg2来传递信息,这比用Bundle更省内存
3.擅用message.what来标识信息,以便用不同方式处理message。