Android0909<十四>(Service、Android线程)
来源:互联网 发布:unity3d obj 文件导入 编辑:程序博客网 时间:2024/05/17 08:46
Service
利用Service做一个虚拟进度条
ProgressBar进度条,progress可以设置默认的进度
在activity_main.xml中加入进度条
<ProgressBar style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/progressBar" android:layout_gravity="center_horizontal" android:progress="50"/> <Button android:id="@+id/start_download" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开始下载"/>
设置线程,通过启动服务来启动线程,线程启动进度,
MyService.java
public class MyService extends Service{ private int count; @Nullable @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); Log.d("运行到了","onCreate"); } @Override public void onDestroy() { super.onDestroy(); Log.d("运行到了","onDestroy"); } @Override public int onStartCommand(final Intent intent, int flags, int startId) { Log.d("运行到了","onStartCommand"); new Thread(new Runnable() { @Override public void run() { while(count<100){ if (count>100){ count=0; } count++; Intent intent1=new Intent(); intent1.setAction(MainActivity.DOWN_LOAD_ACTION); intent1.putExtra("count",count); sendBroadcast(intent1); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); return super.onStartCommand(intent, flags, startId); }}
进行动态注册,在Activity_Manifest.xml中注册
<service android:name=".MyService"></service>
在MainActivity.java中进行设置监听事件
public class MainActivity extends Activity { private Button btn_start_service; private Button btn_stop_service; private Button btn_start_download; private ProgressBar progressBar; private MyDownLoadService mDownLoadService; public static final String DOWN_LOAD_ACTION="com.service.text"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_start_service= (Button) findViewById(R.id.start_service); btn_start_service.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(getApplicationContext(),MyService.class); startService(intent); } }); btn_stop_service= (Button) findViewById(R.id.stop_service); btn_stop_service.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(getApplicationContext(),MyService.class); stopService(intent); } }); mDownLoadService=new MyDownLoadService(); IntentFilter filter=new IntentFilter(); filter.addAction(DOWN_LOAD_ACTION); registerReceiver(mDownLoadService,filter); progressBar= (ProgressBar) findViewById(R.id.progressBar); btn_start_download= (Button) findViewById(R.id.start_download); btn_start_download.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(getApplicationContext(),MyService.class); startService(intent); } }); } class MyDownLoadService extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { int count=intent.getIntExtra("count", 0); progressBar.setProgress(count); } } //解绑,取消广播 @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(mDownLoadService); }}
Service是运行在主线程中,第一次运行时会调用onCreate()、onStartCommand(),当第二次启动时只会调用onStartCommand(),而当只在后台允许一个耗时操作时就要用到IntentService,IntentService本身包含一个线程,包含一个消息队列,会将后续的消息排在队列中,然后等待前面的消息运行结束后,在进行处理后续的消息。
在activity_main.xml中添加一个按钮
<Button android:id="@+id/start_download_intentservice" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开始intentservice下载"/>
写一个MyIntentService.java类,继承于IntentService,要在AndroidManifest.xml中注册
<service android:name=".MyIntentService"></service>
public class MyIntentService extends IntentService{ private int count; /** * Creates an IntentService. Invoked by your subclass's constructor. * * @param name Used to name the worker thread, important only for debugging. */ public MyIntentService(String name) { super(name); } public MyIntentService() { this(""); } @Override protected void onHandleIntent(Intent intent) { Log.d("IntetnService","运行到了OnCreate"); while(count<100){ if (count>100){ count=0; } count++; Intent intent1=new Intent(); intent1.setAction(MainActivity.DOWN_LOAD_ACTION); intent1.putExtra("count",count); sendBroadcast(intent1); try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } Log.d("IntetnService","运行到了onStartCommand"); }}
在MainActivity.java中添加点击事件
public class MainActivity extends Activity { private Button btn_start_service; private Button btn_stop_service; private Button btn_start_download; private Button btn_intentservice; private ProgressBar progressBar; private MyDownLoadService mDownLoadService; public static final String DOWN_LOAD_ACTION="com.service.text"; private AlarmManager mAlarmManager; private BroadcastReceiverActivity mBroadcast; private android.content.ContentResolver resolver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_start_service= (Button) findViewById(R.id.start_service); btn_start_service.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(getApplicationContext(),MyService.class); startService(intent); } }); btn_stop_service= (Button) findViewById(R.id.stop_service); btn_stop_service.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(getApplicationContext(),MyService.class); stopService(intent); } }); mDownLoadService=new MyDownLoadService(); IntentFilter filter=new IntentFilter(); filter.addAction(DOWN_LOAD_ACTION); registerReceiver(mDownLoadService,filter); progressBar= (ProgressBar) findViewById(R.id.progressBar); btn_start_download= (Button) findViewById(R.id.start_download); btn_start_download.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(getApplicationContext(),MyService.class); startService(intent); } }); btn_intentservice= (Button) findViewById(R.id.start_download_intentservice); btn_intentservice.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent=new Intent(getApplicationContext(),MyIntentService.class); startService(intent); } }); } class MyDownLoadService extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { int count=intent.getIntExtra("count", 0); progressBar.setProgress(count); } } //解绑 @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(mDownLoadService); }}
Android线程
利用线程更新UI界面,Hanler()
UI界面只允许主线程来更改UI界面绘制,不允许其他线程来更改界面的绘制,给否则会报错抛出异常。因此就需要想要更改UI界面的线程将要更改界面的消息通过Message传递给主线程,由主线程来完成界面的绘制,当有多条消息时,主线程会将这些消息放在一个消息队列中,等待主线程的处理,通过Handler将消息转递给主线程,然后通过Handler的handleMessage() 方法来对消息进行处理。
Message msg=new Message();msg.obj=count+"秒";msg.what=TIME_DESC;mhandler.sendMessage(msg);
Handler
private Handler mhandler=new Handler(){ public void handleMessage(Message msg){ Log.d("秒数",""+count+msg); switch(msg.what){ case TIME_DESC: String time= (String) msg.obj; btn_handler.setText(time); break; } } };
这里就以倒计时定时器为例,界面activity_main.xml
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="倒计时"/> <Button android:id="@+id/btn_handler" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="60秒"/>
MainActivity.java
public class MainActivity extends Activity { private int count=60; private static final int TIME_DESC=0x23; private Button btn_handler; private Handler mhandler=new Handler(){ public void handleMessage(Message msg){ Log.d("秒数",""+count+msg); switch(msg.what){ case TIME_DESC: String time= (String) msg.obj; btn_handler.setText(time); break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btn_handler= (Button) findViewById(R.id.btn_handler); btn_handler.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { count=60; Toast.makeText(getApplication(),"开始倒计时",Toast.LENGTH_SHORT).show(); new Thread(new Runnable() { @Override public void run() { while (count>0){ count--; try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } Message msg=new Message(); msg.obj=count+"秒"; msg.what=TIME_DESC; mhandler.sendMessage(msg); Log.d("秒数",""+count+msg); } } }).start(); } }); }
但这样写代码会有写繁琐,为了简洁,采用另外一种方法可以达到同样效果,前者使通过主线程里的封装好的Looper()方法来管理消息队列,这里我们可以通过一个自定义的Thread类来对消息进行管理,从而简洁了监听事件里的代码。
MainActivity.java中的按钮事件监听事件
public class MainActivity extends Activity { private int count=60; private static final int TIME_DESC=0x23; private Button btnhandler; private Handler handler=new Handler(){ public void handleMessage(Message msg){ Log.d("秒数",""+count+msg); switch(msg.what){ case TIME_DESC: count--; btnhandler.setText(count+"秒"); if (count>0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } handler.sendEmptyMessage(TIME_DESC); } break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnhandler= (Button) findViewById(R.id.btnhandler); btnhandler.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { count=60; handler.sendEmptyMessage(TIME_DESC); } }); }}
子线程更新UI界面使通过子线程给主线程传递消息来更改UI界面,还可以互换一下,子线程可以接收来自主线程的消息。通过调用自定义的线程里的来让主线程发送消息,因此需要先调用启动线程的方法来启动线程里的Handler()来发送消息。
自定义的Thrad,MyThread .java写成内部类
class MyThread extends Thread{ @Override public void run() { Looper.prepare(); mHandler=new Handler(){ @Override public void handleMessage(Message msg) { Log.d("handler","接收到了主线程的消息"); } }; Looper.loop(); }}
MainActivity.java
public class MainActivity extends Activity { private Button btnhandler; private int count=60; private static final int TIME_DESC=0x23; private Handler handler=new Handler(){ public void handleMessage(Message msg){ Log.d("秒数",""+count+msg); switch(msg.what){ case TIME_DESC: count--; btnhandler.setText(count+"秒"); if (count>0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } handler.sendEmptyMessage(TIME_DESC); } break; } } }; private Button btnHandler; private Handler mHandler; class MyThread extends Thread{ @Override public void run() { Looper.prepare(); mHandler=new Handler(){ @Override public void handleMessage(Message msg) { Log.d("handler","接收到了主线程的消息"); } }; Looper.loop(); }} @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnHandler= (Button) findViewById(R.id.btnHandler); btnHandler.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mHandler.sendEmptyMessage(0); } }); btnhandler= (Button) findViewById(R.id.btnhandler); btnhandler.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { count=60; handler.sendEmptyMessage(TIME_DESC); MyThread thread=new MyThread(); thread.start(); } }); }}
AsyncTask
为了子线程更好地对UI进行操作,Android还提提供了Handler之外一种工具AsyncTast。AsyncTast制定了三个参数,Params在执行AsyncTast时传入,可用于后台中进行的任务,Progress后台执行任务时,需要在界面上显示当前的进度,则使用这里的泛型作为进度单位,Result当任务执行完成后,需要对结果进行返回。
AsyncTask的泛型类型
这三个类型被用于一个异步任务,如下:
1. Params,启动任务执行的输入参数
2. Progress,后台任务执行的百分比
3. Result,后台计算的结果类型
4个步骤
当一个异步任务被执行,任务经过四各步骤:
1.onPreExecute(),在UI线程上调用任务后立即执行。这步通常被用于设置任务,例如在用户界面显示一个进度条。
2.doInBackground(Params…),后台线程执行onPreExecute()完后立即调用,这步被用于执行较长时间的后台计算。异步任务的参数也被传到这步。计算的结果必须在这步返回,将传回到上一步。在执行过程中可以调用publishProgress(Progress…)来更新任务的进度。
3.onProgressUpdate(Progress…),一次呼叫 publishProgress(Progress…)后调用 UI线程。执行时间是不确定的。这个方法用于当后台计算还在进行时在用户界面显示进度。例如:这个方法可以被用于一个进度条动画或在文本域显示记录。
4.onPostExecute(Result), 当后台计算结束时,调用 UI线程。后台计算结果作为一个参数传递到这步。
任务实例必须创建在 UI线程
线程规则
有一些线程规则必须去遵守,这个类才会正确的工作:任务实例必须创建在 UI线程
execute(Params…)必须在UI线程上调用
不要手动调用onPreExecute(), onPostExecute(Result), doInBackground(Params…), onProgressUpdate(Progress…)
这个任务只执行一次(如果执行第二次将会抛出异常)
一个简单的自定义的AsyncTast,MyDownLoadService.java
class MyTask extends AsyncTask<String,String ,String>{ @Override protected void onPostExecute(String s) { super.onPostExecute(s); btn_progressBar.setText(s); } @Override protected void onProgressUpdate(String... values) { super.onProgressUpdate(values); int count1=Integer.parseInt(values[0]); mprogressBar.setProgress(count1); } @Override protected String doInBackground(String... params) { while(count1<101){ count1++; publishProgress(""+count1); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } return "下载已完成"; }}
依旧以下载进度条为例。MainActivity.java
public class MainActivity extends Activity { private Button btn_progressBar; private ProgressBar mprogressBar; private int count1=0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mprogressBar= (ProgressBar) findViewById(R.id.progressBar2); btn_progressBar= (Button) findViewById(R.id.btn_progressBar); btn_progressBar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { MyTask task=new MyTask(); task.execute("去执行吧"); } }); class MyTask extends AsyncTask<String,String ,String>{ @Override protected void onPostExecute(String s) { super.onPostExecute(s); btn_progressBar.setText(s); } @Override protected void onProgressUpdate(String... values) { super.onProgressUpdate(values); int count1=Integer.parseInt(values[0]); mprogressBar.setProgress(count1); } @Override protected String doInBackground(String... params) { while(count1<101){ count1++; publishProgress(""+count1); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } return "下载已完成"; }}}
activity_main.xml
<ProgressBar style="?android:attr/progressBarStyleHorizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/progressBar2" /> <Button android:id="@+id/btn_progressBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="开始"/>
- Android0909<十四>(Service、Android线程)
- Android学习笔记(十四)———Service学习
- android 高级之旅 (十四) Service完全解析 上
- Android Service介绍(Service与线程关系)
- Android Service 线程问题
- Android Service 线程问题
- Android Service 线程问题
- Android Service 线程
- android中service与线程
- Android-Service通知与线程
- Android学习指南之十四:Service详解及应用实例
- Android系统--输入系统(十四)Dispatcher线程情景分析_dispatch前处理
- Android activity与service中的子线程 (入门级)
- Android中Service(服务)和Thread(线程)的关系
- Android学习笔记(十四)
- Android笔记(十四)WebView
- <Android 基础(十四)> selector
- Android开发学习笔记十四 异步线程之AsyncTask
- cent python3离线安装setuptools
- cvc-complex-type.2.4.a: Invalid content was found
- shell-find使用
- 黑马程序员--抽象类和接口
- Android 开源框架Universal-Image-Loader完全解析(一)
- Android0909<十四>(Service、Android线程)
- 注册表查询示例代码
- linux sync
- 我就是一根儿筋 也许问题很简单
- 程序员应该扪心自问的10个问题
- JSP页面中的标签以及内置对象request等
- 批量删除svn隐藏文件
- javaScript: 逻辑运算符
- openlog、syslog和closelog函数