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

关于Android4.0不能再线程下改变UI的解决方案

2014-11-18 22:03 169 查看
前几天,参加上海hack马拉松比赛,合作完成了一个简单的住房android手机应用,其中,就遇到了线程与ui变化的冲突,

队友Android的刚入门,于是,我负责了Android的网络和数据传输部分,队友设计布局和界面。

问题还原:

用户按下按钮的时候,httpclient根据需要发起json数据请求连接到php后端,后端收到数据进行处理后,返回给Android的http线程,然后Android端口的httpclient线程接受数据并对数据进行处理,并最终调整ui界面的状态。

但是,在click监听事件下,直接调用httpclient会导致报错

问题原因:

button的click事件的监听状态下http线程不被允许改变ui界面。

解决方案:

新建一个线程,然后在线程下运行httpclient,将接受到的数据使用bundle进行包装,放入message对象中,传输给相应的handler进行处理

代码:

根据上面描述,得到 rcp类和ecpProxy类,rcpProxy是继承线程的,调用实际的rcp进行http连接和response的处理。

实例代码:

public class RPCProxy extends Thread{

private RPC rpc = null;

public RPCProxy(RPC rpc) {

this.rpc = rpc;

}

@Override

public void run() {

// TODO Auto-generated method stub

rpc.getResponse();

}

}

public class RPC {

private List<NameValuePair> pairList = null;

private String base_Url = "";

private Handler handler = null;

private int choice = 0;

// private JSONObject object = null;

public RPC(List<NameValuePair> pairList_param, String base_url_param,

Handler handler_param) {

base_Url = base_url_param;

pairList = pairList_param;

this.handler = handler_param;

// this.object = object;

}

public RPC(List<NameValuePair> pairList_param, String base_url_param,

Handler handler_param,int choice) {

base_Url = base_url_param;

pairList = pairList_param;

this.handler = handler_param;

this.choice = choice;

// this.object = object;

}

public void getResponse() {

// assert(pairList!=null);

try {

if(pairList!=null){

HttpEntity requestHttpEntity = new UrlEncodedFormEntity(

this.pairList, HTTP.UTF_8);

HttpPost httpPost = new HttpPost(this.base_Url);

httpPost.setEntity(requestHttpEntity);

HttpClient httpClient = new DefaultHttpClient();

HttpResponse response = httpClient.execute(httpPost);

// assert(response!=null);

//调用response的处理,这里就不做response的等待时延的问题了

dealResponse(response);

}else{

Message message = new Message();

message.what=1;

handler.sendMessage(message);

}

} catch (Exception e) {

e.printStackTrace();

// 暂时不做处理

}

}

// public abstract void dealResponse(HttpResponse response);

public void dealResponse(HttpResponse response) {

// TODO Auto-generated method stub

if (null == response) {

return;

}

HttpEntity httpEntity = response.getEntity();

try {

String strResult = EntityUtils.toString(httpEntity);

Message message = new Message();

Bundle bundle = new Bundle();

bundle.putString("result", strResult);

message.setData(bundle);

handler.sendMessage(message);

} catch (Exception e) {

e.printStackTrace();

}

}

使用MainActivity进行测试

先定义一个handler消息处理对象

//获取收藏的handler,这里传回来的数据是json的数组,进行处理

private Handler handler1_get_collection = new Handler() {

public void handleMessage(android.os.Message msg) {

Bundle res = msg.getData();

try {

JSONArray array = new JSONArray(res.getString("result"));

JSONObject obj = array.getJSONObject(0);

// text.setText("Hello"+obj);

text.setText("Coming here->"+obj.getString("house_id")+"->"+obj.getString("house_infomation")+

"->"+obj.getString("house_price")+"->"+obj.getString("house_address")+

"->"+obj.getString("owner_id"));

} catch (JSONException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

// text.setText("Coming here"+res.getString("result"));

super.handleMessage(msg);

}

};

//收房租,这里传回来的数据是json的对象,进行处理

private Handler handler1_get_money = new Handler() {

public void handleMessage(android.os.Message msg) {

Bundle res = msg.getData();

//登陆的判断

if(res.getString("feeCharging").equals("false")){

text.setText("收房租失败啊"+res.getString("feeCharging"));

}else{

text.setText("收房租成功啊"+res.getString("feeCharging"));

}

super.handleMessage(msg);

}

};

private Handler handler1_get_money = new Handler() {

public void handleMessage(android.os.Message msg) {

Bundle res = msg.getData();

JSONObject array = new JSONAObject(res.getString("result"));

if(res.getString("feeCharging").equals("false")){

text.setText("收房租失败啊"+res.getString("feeCharging"));

}else{

text.setText("收房租成功啊"+res.getString("feeCharging"));

}

super.handleMessage(msg);

}

};

按钮绑定事件:

Button button = (Button) findViewById(R.id.send);

button.setOnClickListener(new OnClickListener() {

NameValuePair pair1 = new BasicNameValuePair("user_id","2");
//根据存储的字段

List<NameValuePair> pairList = new ArrayList<NameValuePair>();

pairList.add(pair1);

final RPC rpc = new RPC(pairList,"http://hacksh.sinaapp.com/getCollectInfo.php",handler1_get_collection); //第一个参数是键值对列表,传给后台的参数,第二个是后台的url地址,第三个相应的handler处理程序,

new RPCProxy(rpc).start(); //通过rpcProxy代理实现rpc的功能

}

只要通过改变rpc的url和键值对列表的信息,并给出相应的handler处理对象,就可以了,其他的都不要变化,很好的分离了网络后台和界面前台

最后,说说这次比赛的感想吧。我们小组四个人,通过一天一夜的操作,完成了这个作品,劳动强度很大,通过重构代码,开发速度大大提升,整体架构比较常规php+mysql+json+Android+httpclient完成,整体很nice,但是别人的作品更加优秀,使用leap motion、3D打印机完成了很多优秀的作品,很遗憾的和大奖擦身而过。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: