您的位置:首页 > 移动开发 > Android开发

初学安卓踩过的坑和心得体会(二)——Service

2018-01-07 15:53 162 查看

今天整理的是安卓四大基本组件中的第二个组件——service

首先和前面一样,新建工程,在和mainActivity同级目录下新建一个EcohService的java文件,我是为了好记,名字不重要,自己可以随便起。
新建之后我们将它在manifests.xml中进行注册。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.koogllz.myservices">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".EcohServices"></service>
</application>

</manifest>
如倒数第三行
接下来在activity_main.xml中新建两个按钮,直接在design界面拖拽两个按钮即可
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="start" />

<Button
android:id="@+id/button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="stop" />
接下来在mainActivity中进行声明和绑定id
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnStart=findViewById(R.id.button);
        btnStop=findViewById(R.id.button2);
        i=new Intent(this, EcohServices.class);
        btnStart.setOnClickListener(this);
        btnStop.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            case R.id.button:
                startService(i);
                break;
            case R.id.button2:
                stopService(i);
                break;
        }
    }
}
其中的this是因为想使用同一个监听器事件,能够读取当前service的状态,能够继续操作,所以将本类作为onclickListener的实现类,下面的onClick方法是重写方法。
intent是作为其中传递的对象而存在。
下面做一个分支,如果点击到了button就执行开始,点击到了button2就执行结束。
回到ecohServices.java中,将其继承services,并且写入onCreate和onDestroy方法
public class EcohServices extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {//继承Service后不要忘记重写此方法
return null;
}

@Override
public void onCreate() {
System.out.println("create");
super.onCreate();
}

@Override
public void onDestroy() {
System.out.println("destroy");
super.onDestroy();
}
}
接下来就可以在虚拟机中运行了,我们可以发现在点击button1时会出现create字样,点击button2会出现destroy字样,证明我们绑定成功了。
接下来就是在Service中进行通信,需要用到Service绑定。
我们在activity_main.xml中新建两个按钮“绑定”和“解绑”(这里不再赘述代码)并且在两个按钮上增加this监听器,在下面的onclick事件分支上新建这两个按钮按下后的操作。

public class MainActivity extends Activity implements View.OnClickListener, ServiceConnection {
private Button btnStart,btnStop,bund,unbund;

private Intent i;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

btnStart=findViewById(R.id.button);
btnStop=findViewById(R.id.button2);
bund=findViewById(R.id.bund);
unbund=findViewById(R.id.unbund);
i=new Intent(this, EcohServices.class);
btnStart.setOnClickListener(this);
btnStop.setOnClickListener(this);
bund.setOnClickListener(this);
unbund.setOnClickListener(this);

}

@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.button:
startService(i);
break;
case R.id.button2:
stopService(i);
break;
case R.id.bund:
bindService(i,this, Context.BIND_AUTO_CREATE);//这里的this是servicConnection类型所以要将本类实现serviceConnection接口。
break;
case R.id.unbund:
unbindService(this);
break;
}
}

@Override//实现serviceConnection接口后的两个方法
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
System.out.println("onservices successful!");
}

@Override
public void onServiceDisconnected(ComponentName componentName) {
//崩溃才会用到
}
}

接着我们回到EcohService.java中将onbind方法中打印一个“onbind”字符串,来检验方法执行效果。
运行程序后我们可以看到点击bund按钮他会先create一个Service之后才会执行onbind绑定方法,但是onserviceConnected方法并没有被执行。原因是我们在onbind方法中的返回值null,没有做更改。
此时我们查看onbind方法的但回执是IBinder,我们到api文档中找到了一个系统给的基本的实现类binder,我们在下面写一个内部类,扩展自binder,然后我们将我们的返回值变成这个类的对象即可。
public IBinder onBind(Intent intent) {
System.out.println("onbind");
return serviceBinder;
}
public final SeBinder serviceBinder=new SeBinder();
public class SeBinder extends Binder{

}


我们继续进行调试,发现我们create一个程序之后在点击绑定按钮,他不会再重新create一遍,而进行stop销毁service之后我们直接点击绑定按钮,它会先create一个然后再绑定,输出“onbind”和“serviceConnectied successful!”也就是说在系统中我们cerate一个新的service只会有一个实例化存在。如果要销毁一个程序要同时执行解绑和stop方法才会成功销毁。
如果通过create启动的service在销毁当前activity的时候(比如按后退键)服务是不会停止的,但是如果是通过bind启动的service,在销毁当前activity的时候服务也会被销毁。

接下来我们看一下数据的传递

我们在下面新建两个变量一个是timer,一个是task;
private Timer timer=null;
private TimerTask task=null;
private int i=0;
public  void startTimer(){//新建一个开始计时方法
if (timer==null){
timer=new Timer();
task=new TimerTask() {
@Override
public void run() {//实现timerTask的方法
i++;
System.out.println(i);//让计时器加一
}
};
timer.schedule(task,1000,1000);每隔一秒加一秒
}
}
public void stopTimer(){//新建一个停止计时方法
if(timer!=null){
timer.cancel();
task.cancel();
timer=null;
task=null;
}
}
我们在新建的内部类中创建一个getservice()方法,返回本类当前状态,然后再写一个getCurrentNum()方法能够获得当前状态值。

public IBinder onBind(Intent intent) {
System.out.println("onbind");
return serviceBinder;
}
public final SeBinder serviceBinder=new SeBinder();
public class SeBinder extends Binder{
public EcohServices getservices(){
return EcohServices.this;
}
}

public int getCurrentNum(){
return i;
}

接下来我们回到mainactivity类中获取这个EcohServices
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {//此处自动生成的iBinder
System.out.println("onservices successful!");
ecohServices= ((EcohServices.SeBinder)iBinder).getservices();
}


接下来我们新建一个获取这个值的按钮getnum,方法不再赘述,然后我们在分支判断的时候如果点击了这个按钮我们判断一下ecohservice是否为空,如果他获得了值就证明我们获得了值,成功了所以代码:

case R.id.unbund:
unbindService(this);
ecohServices=null;
break;
case R.id.getnum:
if(ecohServices!=null){
System.out.println("当前值"+ecohServices.getCurrentNum());
}
我们输出获取的值,但是上面的在销毁和解绑的时候我们要记得将值置回null,不然一直是非空就会出现问题。

总结

我们不能自己新建service,只能通过onCreate和onDestroy方法申请系统为我们创建。
在多个按钮分享同一个状态的时候我们可以使用本类作为监视对象,在onclick方法中进行分支比较,做出相应的反应,也可以大大提升效率。
传递值和传递对象的逻辑要自己掌握清楚
写了一个判断条件要想一想什么时候应出现相反的条件约束,以便程序能够正常循环。
进行某种带有新的接口类型的时候可以使用本类实现接口即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息