您的位置:首页 > 产品设计 > UI/UE

【Android】安卓开发之通过本地广播实现子线程和UI线程的通信

2017-02-26 17:57 701 查看
在做一个demo的时候,需要实现一个效果:当用户进行一些耗时操作的时候,显示一个进度条对话框,避免用户产生程序没反应的体验。而耗时操作一般都是在子线程中进行,而且如果耗时操作在子线程调用的外部类当中,那我们要如何让子线程将消息通知给UI线程,让UI线程及时的显示和收回进度条对话框呢?方法还是有的,比如说使用本地广播。

一、在子线程调用的外部类里,进行本地广播发送设置:

public class SendPostRequest {
//-----------------------------声明一个本地广播管理器-------------------------------------------
private LocalBroadcastManager localBroadcastManager;
//----------------------------------------------------------------------------------------------
public String sendPostRequest(String url, String param,Context context) {
//-------------------------获取本地广播管理器的实例-----------------------------------------
localBroadcastManager = LocalBroadcastManager.getInstance(context);
//------------------------------------------------------------------------------------------
//-------------------------要发送的广播消息,使用intent作为载体-----------------------------
Intent intentEN = new Intent("LOCAL_BROADCAST_EN_PROGRESS_DIALOG");
Intent intentDIS = new Intent("LOCAL_BROADCAST_DIS_PROGRESS_DIALOG");
//------------------------------------------------------------------------------------------
HttpURLConnection httpURLConnection = null;
OutputStream out = null; //写
InputStream in = null;   //读
int responseCode = 0;    //远程主机响应的HTTP状态码
String result = "";
try {
URL sendUrl = new URL(url);
httpURLConnection = (HttpURLConnection) sendUrl.openConnection();
//post方式请求
httpURLConnection.setRequestMethod("POST");
//设置头部信息
httpURLConnection.setRequestProperty("headerdata", "ceshiyongde");
//一定要设置 Content-Type 要不然服务端接收不到参数
httpURLConnection.setRequestProperty("Content-Type", "application/Json; charset=UTF-8");
//指示应用程序要将数据写入URL连接,其值默认为false(是否传参)
httpURLConnection.setDoOutput(true);
//httpURLConnection.setDoInput(true);
httpURLConnection.setUseCaches(false);
//--------------------发送弹出进度条对话框的本地广播------------------------------------
localBroadcastManager.sendBroadcast(intentEN);
//--------------------------------------------------------------------------------------
httpURLConnection.setConnectTimeout(5000); //5秒连接超时
httpURLConnection.setReadTimeout(3000);    //5秒读取超时
//传入参数
out = httpURLConnection.getOutputStream();
out.write(param.getBytes());
out.flush(); //清空缓冲区,发送数据
out.close();
responseCode = httpURLConnection.getResponseCode();
//获取请求的资源
BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), "UTF-8"));
result = br.readLine();
} catch (Exception e) {
e.printStackTrace();
}
Map<String, String> map = new Gson().fromJson(result, new TypeToken<Map<String, String>>() {
}.getType());
String msg = "";
try{
msg = map.get("msg");
}catch (NullPointerException ne){
Log.i("tag","网络连接异常");
}
//--------------------发送关闭进度条对话框的本地广播----------------------------------------
localBroadcastManager.sendBroadcast(intentDIS);//后台不开的情况下,读取超时不起作用
//------------------------------------------------------------------------------------------
return msg;
}
}


二、在UI线程里进行本地广播接收设置

public class RegisterPart2 extends BaseActivity {
private final int PASSDIFF = 0;
private final int LENLESS = 1;
private final int REGSUCCESS = 2;
private final int REGEXIST = 3;
private final int REGFAIL = 4;
private final int EN_PROCESSDIALOG = 5;
private final int DIS_PROCESSDIALOG = 6;
private String userName;
private IntentFilter intentFilter_en;
private IntentFilter intentFilter_dis;
private LocalReceiver localReceiver;
private LocalBroadcastManager lm;
AlertDialog.Builder dialog;
//对象的获得不能放在Handler里,不然会重复创建,然后指向的不是一个对象,导致进度条对话框无法关闭
ProgressDialog pd;
//--------------------------------------------定义一个Handler来处理消息-------------------------
final Handler handler = new Handler() {
@Override
public void handleMessage(Message message) {
switch (message.what) {
case PASSDIFF:
dialog.setMessage("两次输入的密码不一致!");
dialog.setCancelable(false);
dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {

}
});
dialog.show();
break;
case LENLESS:
dialog.setMessage("密码长度不足8位!");
dialog.setCancelable(false);
dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {

}
});
dialog.show();
break;
case REGSUCCESS:
dialog.setMessage("注册成功!");
dialog.setCancelable(false);
dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {
//注册成功则跳转到登陆页面,不成功不跳转
Intent intent = new Intent(RegisterPart2.this, Login.class);
startActivity(intent);
ActivityCollector.finishAll();
}
});
dialog.show();
break;
case REGEXIST:
dialog.setMessage("注册的账户已经存在!");
dialog.setCancelable(false);
dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {

}
});
dialog.show();
break;
case REGFAIL:
dialog.setMessage(message.obj+" 一定出了什么问题。。。╮(╯▽╰)╭ ");
dialog.setCancelable(false);
dialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int which) {

}
});
dialog.show();
break;
case EN_PROCESSDIALOG://显示进度条对话框
pd.setCancelable(true);
pd.setMessage("请稍候......");
pd.show();
break;
case DIS_PROCESSDIALOG://关闭进度条对话框
pd.dismiss();
break;
default:
break;
}
}
};
//----------------------------------------------------------------------------------------------
@Override
protected void onDestroy(){
super.onDestroy();
//---------------------------当活动被销毁时,注销本地广播接收器-----------------------------
lm.unregisterReceiver(localReceiver);
//------------------------------------------------------------------------------------------
}

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

dialog = new AlertDialog.Builder(RegisterPart2.this);//对话框
pd = new ProgressDialog(RegisterPart2.this);//获取进度条对话框的对象

//---------------------------注册本地广播---------------------------------------------------
intentFilter_en = new IntentFilter();
intentFilter_dis = new IntentFilter();
intentFilter_en.addAction("LOCAL_BROADCAST_EN_PROGRESS_DIALOG");
intentFilter_dis.addAction("LOCAL_BROADCAST_DIS_PROGRESS_DIALOG");
localReceiver = new LocalReceiver();//获取本地广播接收器的对象
lm = LocalBroadcastManager.getInstance(this);//获取本地广播管理器的对象
lm.registerReceiver(localReceiver,intentFilter_en);
lm.registerReceiver(localReceiver,intentFilter_dis);
//------------------------------------------------------------------------------------------

//---------------------------给状态栏设置颜色-----------------------------------------------
TextView textViewActionBar = (TextView) findViewById(R.id.actionBarId);
setActionBarColor(textViewActionBar, getResources().getColor(R.color.theRed));
//------------------------------------------------------------------------------------------
//----------------------------使用Intent解析上一个活动传来的数据----------------------------
Intent intent = getIntent();
userName = intent.getStringExtra("userName");
//------------------------------------------------------------------------------------------
final EditText regUserName = (EditText) findViewById(R.id.regist2NameEditId);
final EditText regPassword = (EditText) findViewById(R.id.regist2PasswordEditId);
final EditText regConfirm = (EditText) findViewById(R.id.regist2ConfirmEditId);
EditText regEmail = (EditText) findViewById(R.id.regist2EmailEditId);
Button confirmButton = (Button) findViewById(R.id.regist2ConfirmBottonId);

/**
* 完成注册,销毁之前的注册活动,直接跳到登陆界面,且不可返回之前注册活动
*/
confirmButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//----------------------------------收回软键盘--------------------------------------
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(),0);
}
//----------------------------------------------------------------------------------
//---------------------通过POST请求将用户名和密码发送给服务器-----------------------
try {
//新建一个线程,通过Message消息通知Handle对UI进行更改,现在只能在UI线程里对UI组件进行更改。
new Thread(new Runnable() {
@Override
public void run() {
String password = regPassword.getText().toString();
String confirmPassword = regConfirm.getText().toString();
Message message = new Message();
if (!(password.equals(confirmPassword))) {//如果输入的密码不一致
message.what = PASSDIFF;
handler.sendMessage(message);
return;
}
if (password.length() < 8) {//如果输入的密码长度小于8位
message.what = LENLESS;
handler.sendMessage(message);
return;
}
//下面三句话,将会把三个参数包装为{"para1":10,"para2":2,"opt":"div"}字段
CalBean tb = new CalBean(userName, password);
Gson gson = new Gson();
String datas = gson.toJson(tb);
String url = " http://10.10.120.43:8080/Register"; SendPostRequest sendPostRequest = new SendPostRequest();
String data = sendPostRequest.sendPostRequest(url,datas,RegisterPart2.this);
//根据返回来的数据进行判断是否注册成功
if (data.equals("注册成功")) {
message.what = REGSUCCESS;
handler.sendMessage(message);
return;
} else if (data.equals("账户已存在")) {
message.what = REGEXIST;
handler.sendMessage(message);
return;
} else {
message.what = REGFAIL;
message.obj = data.toString();
handler.sendMessage(message);
return;
}
}
}).start();
} catch (Exception e) {
Log.i("ok", "there must be something wrong!");
return;
}
//----------------------------------------------------------------------------------
}
});
}
//------------------------------------重写本地广播接收器----------------------------------------
class LocalReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context,Intent intent){
switch (intent.getAction()){
case "LOCAL_BROADCAST_EN_PROGRESS_DIALOG":
Message en_message = new Message();
en_message.what = EN_PROCESSDIALOG;
handler.sendMessage(en_message);
break;
case "LOCAL_BROADCAST_DIS_PROGRESS_DIALOG":
Message dis_message = new Message();
dis_message.what = DIS_PROCESSDIALOG;
handler.sendMessage(dis_message);
break;
default:break;
}
}
}
//----------------------------------------------------------------------------------------------
}


效果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐