Android0909<十四>(Service、Android线程)

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="开始"/>

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值