有关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 Process3.ServiceProcess4.Background Process5.Empty Procecc)在系统内存资源不够的时候,系统会首先将等级较低的进程杀死来满足其他高等级的进程正常运行,而service正处于第三等级,而被覆盖住的Activiy处于第四等级,这样当我们在运行程序时因为某种原因而将当前Activity覆盖,那我们在该Activity中的很多操作尤其需要网络交互的很可能会因为系统内存资源不足,而将其杀掉。这样就会导致数据的不完成,使程序的鲁棒性不够强,而如果将他们都放在service中实现那就稳妥多了,程序也相对稳定多了。当然程序的稳定性是由很多因素构成的,这只是其中之一而已。那好,既然说放在service中操作,那就在那儿操作吧,这不就完了吗,可是就在我们准备这样做时,总会意识到一个问题,当我们把这些操作统统放到service中实现时,那Activity的中控件的更新怎么办,比如因为播放总会有进度条的,文件下载也是要时时更新下载量的,不知道各位怎么处理这个问题的,我在网上查了查,看到的方法都是通过广播,即在 Activity中注册一个广播,然后通过广播进行service和Activity间的数据传递,同时以达到更新UI的目的,虽然我没这么做过,但我知道这是可以的,但我总觉的,这样有点劳师动众了,而且我曾经用了一次广播,根据我的使用的效果来说觉得广播不适合做一些时时更新的操作(具体原因我没有深入研究过,不敢过多评论),反应不够及时。所以我自己就试着用别的方法进行UI更新,最后我觉得通过Binder对象实现,怎么实现我就不用文字说明了,下面我就随便写了个例子简单说明。抛砖引玉吧
用来更新UI的service
1 package com.gqs.service; 2 3 import android.app.Service; 4 import android.content.Intent; 5 import android.os.Binder; 6 import android.os.Handler; 7 import android.os.IBinder; 8 import android.os.Message; 9 import android.widget.TextView;10 11 public class UpdateService extends Service {12 private int data;13 private Handler handler;14 15 @Override16 public IBinder onBind(Intent intent) {17 // TODO Auto-generated method stub18 return new MyBinder();19 }20 21 public class MyBinder extends Binder {22 public void setDate(final TextView tv, final UpdateData updata) {23 new Thread(new MyThread()).start();24 handler = new Handler() {25 public void handleMessage(Message msg) {26 updata.update(tv, data);27 }28 };29 }30 }31 32 public class MyThread implements Runnable {33 34 @Override35 public void run() {36 while (true) {37 data++;38 Message msg = handler.obtainMessage();39 msg.arg1 = data;40 handler.sendMessage(msg);41 try {42 Thread.sleep(1000);43 } catch (InterruptedException e) {44 // TODO Auto-generated catch block45 e.printStackTrace();46 }47 }48 }49 50 }51 52 public interface UpdateData {53 public void update(TextView tv, int data);54 55 }56 }
用来显示的Activity
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:android="http://schemas.android.com/apk/res/android" 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:id="@+id/textView" android:text="@string/hello" /> <Button android:text="开始" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnStart" /></LinearLayout>
大致就是这样 代码很简单,通过继承Binder类和一个回调方法实现对view的更新。当然如果不要回调方法也可以,那就直接在handleMessage()中进行数据更新也是可以,但我觉的加个回调方法会更灵活一些。。。
好了差不多就这些吧,说的不好,还望各位方家多多指教,不胜感激!!!
更多相关文章
- 用DownLoadManage封装一个App的更新组件(兼容android 6、7、8)
- Android之Android(安卓)apk动态加载机制的研究
- Android(安卓)超级轻量的版本更新库AppUpdate
- 【Bugly干货分享】手把手教你逆向分析 Android(安卓)程序
- Android从驱动层到应用程序层的通信
- Android(安卓)模拟按键H5点击方案探究
- 如何完全退出单例模式下的android应用程序,非常好用
- 必应为Android和iOS平台的新版必应应用
- 【设计模式与Android】备忘录模式——在齐太史简