2 mshuaia mshuaia 于 2014.12.11 15:11 提问

Android UI耗时问题处理

问题描述:UI中btn的一个响应有耗时操作,另起线程来执行,UI依然有卡顿

代码描述如下:
public class MyActivity extends Activity {

Button btnSend;
protected void onCreate(Bundle savedInstanceState) {
    .....
    btnSend=(Button) findViewById(R.id.btn_send);
    btnSend.setOnclickListener(mListener);
}

OnClickListener mListener=new new View.OnClickListener() {

        @Override
        public void onClick(View v) {
         new Thread(sendable).start();  
        }
}

Runnable sendable = new Runnable() {
    @Override
    public void run() {
        String data="data";
        sendRemote(data);
    }
}

/***因为具体的发送方法在服务里,所以此处传递消息给
****服务处理,发送函数是一个耗时操作,发送之后等待回复或等至超时***/
private void sendRemote(String strData){    
    Intent iSend=new Intent("send");    
    iSend.putExtra("data", msg);
    startService(iSend);
}

}
在这种情况下会有一个明显的卡顿,我的疑问是:
1、另起线程并没有完全将耗时程序从UI中剥离开来吗?
2、即使未剥离开,UI线程启动服务的操作也要一直等到 服务按要求启动并执行相应的步骤(此处为发送信息)之后才算完成吗?要不然也不应该卡顿啊

求高手指点,谢谢

7个回答

luowenlong860502
luowenlong860502   2014.12.11 17:16
已采纳

问题比较明显,肯定不是出在你贴出来的代码中,请检查你启动的service的oncreate函数,看里面是不是做了耗时操作,
service也是运行于UI线程,请在service的oncreate中创建thread做耗时操作

mshuaia
mshuaia 谢谢回答,oncreate()里面没有耗时程序,不过你说的service也是运行UI线程的话,那问题就显而易见了,我的做法就相当于从UI线程启动新线程来,然后新线程又把耗时操作交给了UI线程,所以卡顿
接近 3 年之前 回复
mshuaia
mshuaia   2014.12.11 15:29

自己先补充一下,对于第一个问题,有测试过,若是不以启动服务的方式来执行发送操作,没有卡顿。

91program
91program   Ds   Rxr 2014.12.11 15:32

1 启动一个线程,就为了启动服务,个人认为这个完全没有必要。
2 卡,可能与服务中的实现有关,与 MyActivity 无关。

mshuaia
mshuaia 好像在评论里贴代码好乱啊
接近 3 年之前 回复
mshuaia
mshuaia 启动线程并不是为了启动服务,我们知道服务启动了之后,再启动,只是会执行onStartCommand()方法来处理相应的请求,我的onStartCommnd()方法如下
接近 3 年之前 回复
mshuaia
mshuaia   2014.12.11 16:31
public int onStartCommand(Intent intent, int flags, int startId) {
    Log.v(strTag, "onStart");       
    if(intent.getAction().equals("connect")){
        Log.v(strTag, "df_connect");        
    .....
    }else if (intent.getAction().equals("send")) {
     final String bContent=intent.getStringExtra("data");
        Log.v(strTag, "接收到来自Activity的发送数据:"+bContent);          
        doSendData(bContent);
    }else if (intent.getAction().equals("close")) {
        isRun=false;
        stopService(intent);
        Log.v(strTag, "df_MainService has been stoped");
    }
    return super.onStartCommand(intent, flags, startId);
}
a107473515
a107473515   2014.12.11 18:32

关键代码没有贴出来,先要确定是什么业务耗时,耗时业务不要放在ui线程里面处理,另开线程,不是另开服务。

mshuaia
mshuaia 谢谢回答,从我的代码来看,是新开了线程的,不是开服务,因为服务早就启动了,当我再次启动服务的时候,不会再执行onCreate(),而是直接执行onStartCommond()方法,我的发送操作在这个方法里
接近 3 年之前 回复
mshuaia
mshuaia   2014.12.12 10:47

在此处结个贴:
感谢大家的热心回答,盒子童鞋的回答是正解,问题的关键在于Service也运行于UI线程,所以,虽然在UI响应里另起了线程来处理耗时,但最后,新线程又
把问题抛回给了UI线程,所以导致卡顿,后来的处理是,在onStartCommond()方法里另起线程处理耗时,问题解决;

Android_app
Android_app   2014.12.12 13:51

我不会告诉你,可以用postDelay

mshuaia
mshuaia 在这里要用postDelay的话比直接新起线程要麻烦一点;
接近 3 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片