[初试Android]Service+跨线程操作GUI的一个小例子
2012-12-27 00:25
323 查看
[初试Android]Service+跨线程操作GUI的一个小例子
1、实验内容
本例子练习使用Service以及控件的跨线程操作:主Activity界面用来启动、停止一个服务,该服务启动后会产生一个线程,该线程每隔一秒产生一个随机双精度数,并将该随机数显示在主Activity界面的一个TextView控件中。2、实现过程
2.1 建立工程
首先建立一个空白的Android工程:工程名为ServiceDemo,程序包存储为per.elton.servicedemo,主Activity为默认名MainActivity。2.2 添加Service实现类
在per.elton.servicedemo下新建一个Service实现类:RandomService,该类继承android.app.Service。并重载该类的三个方法:public class RandomService extends Service { // 服务启动时调用一次 @Override public void onCreate(){} // 服务每次启动都调用一次 @Override public void onStart(Intent intent, int startID){} // 停止服务时调用 @Override public void onDestory(){} @Override public IBinder onBind(Intent arg0) { return null; } }
2.3 布置MainActivity界面
添加两个按钮分别用来启动(btnStartService)和停止服务(btnStopService),添加一个TextView(tvShowRandom)用来显示随机数。布局如下图所示:![](http://img.my.csdn.net/uploads/201212/27/1356539935_2678.png)
Fig 1
2.4 添加事件监听
使MainActivity实现android.view.OnClickListener接口,并添加该接口的实现方法:@Override public void onClick(View v) {}
对于“Start Service”按钮和“Stop Service”:添加对按钮点击事件的处理为如下代码。
@Override public void onClick(View v) { Intent intent = new Intent(this,RandomService.class); switch (v.getId()) { case R.id.btnStartService: // 显示启动服务,知道服务的类以及路径 startService(intent); // 隐式启动服务,不清楚类的更详细细节 /* * Intent intentHiden = new Intent(); * intentHiden.setAction("MY_RANDOM_SERVICE"); * startService(intentHiden); */ break; case R.id.btnStopService: stopService(intent); break; } }
既可以显式启动服务,也可以通过服务在AndroidManifest.xml中的名字(本例服务的名字名为“MY_RANDOM_SERVICE”)来启动服务。服务在XML文件中的设置如下:
<service android:name="RandomService"> <intent-filter> <action android:name="MY_RANDOM_SERVICE"/> </intent-filter> </service>
本例中采用直接指定服务的实现类来启动RandomService这个服务。
在Activity启动时,将事件响应注册到两个按钮上。在onCreate方法中添加如下事件监听器。
Button btnStartService = (Button)findViewById(R.id.btnStartService); Button btnStopService = (Button)findViewById(R.id.btnStopService); btnStartService.setOnClickListener(this); btnStopService.setOnClickListener(this);
2.5 添加updateGUI方法
为了实现RandomService服务所启动的线程对MainActivity中tvShowRandom控件的操作,在MainAcitivity中添加一个静态的方法updateGUI(double),以方便服务中线程的调用。private static TextView tvRandom; // 在onCreate方法中完成赋值 private static double dbRandom; // 服务传递过来的随机数 private static int intIndex=0; // 记录产生的随机数的次数 private static Handler handler = new Handler(); // 接受子线程传递来的数据,并更新UI private static Runnable refreshRunnable = new Runnable() { @Override public void run() { tvRandom.setText(String.valueOf(intIndex++)+" 产生的随机数:"+String.valueOf(dbRandom)); } }; public static void updateGUI(double dbTmp){ dbRandom = dbTmp; handler.post(refreshRunnable); }
关于Handler的更多介绍,http://www.pin5i.com/showtopic-android-handler.html。由于updateGUI方法是静态的,所以该方法涉及到的相关变量也都为静态的。
至此,只要RandomService服务通过调用静态方法updateGUI即可更新主界面的空间内容,也就是显示一个随机数。接下来实现RandomService。
2.6 实现RandomService中的关键方法
RandomServie需要实现2.2中所列出的三个主要方法:onCreate,onStart和onDestory。分别用来在初始化服务阶段、启动服务阶段和注销服务阶段调用。在onCreate方法中需要初始化一个线程,并通过一个Runnable变量指定其要实现的功能。相关代码如下:private Thread rsThread; private Runnable runableWork = new Runnable() { public void run() { try{ while(!Thread.interrupted()){ double dbRandom = Math.random(); MainActivity.updateGUI(dbRandom);// 更新界面 Thread.sleep(1000); // 子线程休眠一秒钟 } } catch (Exception e) { Log.i("RANDOM_SERVICE", "Exception found ... ..."); } } }; @Override public void onCreate(){ super.onCreate(); Toast.makeText(this, "Random service has been created now ... ...", Toast.LENGTH_LONG).show(); // 初始化线程 rsThread = new Thread(null,runableWork,"rsThread"); }
服务的onStart方法在每次RandomService恢复运行或者启动时调用此方法,因此可在此方法中启动子线程,代码如下:
@Override public void onStart(Intent intent, int startID){ super.onStart(intent, startID); Toast.makeText(this, "Random service starts ... ...", Toast.LENGTH_LONG).show(); // 启动线程产生并显示随机数 if (!rsThread.isAlive()){ rsThread.start(); } }
停止RandomService服务:
@Override public void onDestroy(){ super.onDestroy(); Toast.makeText(this, "Random service has been destroied now ... ...", Toast.LENGTH_LONG).show(); rsThread.interrupt(); }
现在所有的编码就完成了,可以直接编译放到机器上运行。本例中,模拟机采用的系统是基于android2.3.3平台的。
3、代码部分以及运行
代码在第二章节已有较详细的介绍,此处将所有的代码打包,点击下载。运行界面如下所示:
![](http://img.my.csdn.net/uploads/201212/27/1356539916_4559.jpg)
Fig 2
4、总结
本例主要是练习如何实现一个服务,以及如何在子线程中操作主线程的GUI。相关文章推荐
- TensorFlow自带例子已经包含了android和ios下的摄像头图像分类示例Inception v1,这里补充一个Windows下的,使用AForge库(www.aforgenet.com)操作
- Linux多线程编程(不限Linux)——本文一个例子展开,介绍Linux下面线程的操作、多线程的同步和互斥。
- Android的Activity启动长时间的操作开启一个Service比开启一个线程好
- 【Android笔记 六】Android Sensor感应器介绍(二)线程中刷新UI 一个创建android测力计的例子
- 一个线程间同步 + FIFO顺序操作链表的例子
- 一个例子展开,介绍Linux下面线程的操作、多线程的同步和互斥。
- 一个例子展开,介绍Linux下面线程的操作、多线程的同步和互斥。
- Android AsyncTask实现一个线程操作完成后启动另一个线程
- 一个完整的操作UI线程的例子,用到了多种方式
- 一个简单的例子解析android中Handler线程和普通Thread的使用
- 本文一个例子展开,介绍Linux下面线程的操作、多线程的同步和互斥
- 线程同步的小例子(两个线程对一个List进行写操作)
- Android GUI 单线程消息队列机制 —— 多线程GUI工具箱:一个破碎的梦
- .net操作带命名空间的xml(仅列一个获取节点值的例子其他以此类推)
- Android一个小球弹跳的例子,希望对大家有用
- Kotlin开发android:一个简单的登陆例子
- Python连接DB2操作的一个小例子
- Android控件之ExpandableListView的一个例子。很不错的哦
- Android---添加一个共享操作
- 关于:读写xls文件,提供下载的一个小例子(jxl 的简单运用) - 高级操作