865
技术社区[云栖]
有关Android中Service实现UI更新(Binder的运用)
我们知道Android的程序架构本身即是遵循MVC模式设计的,将显示和逻辑操作进行了很好的分离。xml文件进行view的添加和布局,Activity来实现各种View的展示,而service实现将数据按一定逻辑在View中显示。基于这样的原则我们设计程序时,就需要做到让他们各司其职,合理搭配,如此才能使我们设计的Android程序更高效,更安全以及易于维护,当然这是一个很大很大很大的话题,此处我只对service和Activity的职责进行简单阐述,希望能起到抛砖引玉的作用,当然若内容如有雷同不胜荣幸.
Service是在Android程序后台运行的组件,比如音乐播放,网络下载等,这些操作的确都可以在service中完成,但并不是说我们只可以再service中完成,在Activity中一样可以实现,那为什么我们还要一个service呢,曾经我也疑惑过,后来我知道了在Android中又五个进程等级(1.Foreground Process: 2.Visible Process 3.ServiceProcess4.Background Process 5.Empty Procecc)在系统内存资源不够的时候,系统会首先将等级较低的进程杀死来满足其他高等级的进程正常运行,而service正处于第三等级,而被覆盖住的Activiy处于第四等级,这样当我们在运行程序时因为某种原因而将当前Activity覆盖,那我们在该Activity中的很多操作尤其需要网络交互的很可能会因为系统内存资源不足,而将其杀掉。这样就会导致数据的不完成,使程序的鲁棒性不够强,而如果将他们都放在service中实现那就稳妥多了,程序也相对稳定多了。当然程序的稳定性是由很多因素构成的,这只是其中之一而已。那好,既然说放在service中操作,那就在那儿操作吧,这不就完了吗,可是就在我们准备这样做时,总会意识到一个问题,当我们把这些操作统统放到service中实现时,那Activity的中控件的更新怎么办,比如因为播放总会有进度条的,文件下载也是要时时更新下载量的,不知道各位怎么处理这个问题的,我在网上查了查,看到的方法都是通过广播,即在 Activity中注册一个广播,然后通过广播进行service和Activity间的数据传递,同时以达到更新UI的目的,虽然我没这么做过,但我知道这是可以的,但我总觉的,这样有点劳师动众了,而且我曾经用了一次广播,根据我的使用的效果来说觉得广播不适合做一些时时更新的操作(具体原因我没有深入研究过,不敢过多评论),反应不够及时。所以我自己就试着用别的方法进行UI更新,最后我觉得通过Binder对象实现,怎么实现我就不用文字说明了,下面我就随便写了个例子简单说明。抛砖引玉吧
用来更新UI的service
package com.gqs.service; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.widget.TextView; public class UpdateService extends Service { private int data; private Handler handler; @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub return new MyBinder(); } public class MyBinder extends Binder { public void setDate(final TextView tv, final UpdateData updata) { new Thread(new MyThread()).start(); handler = new Handler() { public void handleMessage(Message msg) { updata.update(tv, data); } }; } } public class MyThread implements Runnable { @Override public void run() { while (true) { data++; Message msg = handler.obtainMessage(); msg.arg1 = data; handler.sendMessage(msg); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } public interface UpdateData { public void update(TextView tv, int data); } }
package com.gqs.activity; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; import android.os.IBinder; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.gqs.service.UpdateService; import com.gqs.service.UpdateService.MyBinder; import com.gqs.service.UpdateService.UpdateData; public class ServiceToActivityActivity extends Activity { /** Called when the activity is first created. */ private TextView tv; private UpdateService.MyBinder binder; private Button btnStart; private ServiceConnection conn=new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub binder=(MyBinder) service; tv.setText("已连接"); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); btnStart=(Button)findViewById(R.id.btnStart); tv=(TextView)findViewById(R.id.textView); Intent intent=new Intent(this,UpdateService.class); bindService(intent, conn, Context.BIND_AUTO_CREATE); btnStart.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub if(binder!=null) { binder.setDate(tv, new UpdateData() { @Override public void update(TextView tv, int data) { // TODO Auto-generated method stub tv.setText(data+""); } }); } else { Toast.makeText(getApplicationContext(), "连接失败", 1).show(); } } }); } @Override protected void onDestroy() { // TODO Auto-generated method stub unbindService(conn); super.onDestroy(); } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android: android:text="@string/hello" /> <Button android:text="开始" android:layout_width="wrap_content" android:layout_height="wrap_content" android: /> </LinearLayout>
最后更新:2017-04-03 21:30:11