日报2015/10/15(极客学院安卓视频学习)

来源:互联网 发布:男生挂件知乎 编辑:程序博客网 时间:2024/05/20 23:57

Android 中 Context 的理解及使用

Context实际上用来管理访问全局资源

getContext().getResources().getXXX

这行代码就可以访问到全局的字符串、图片等资源

例如给一个TextView设置内容:

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        TextView textView = new TextView(this);        //访问到全局资源:字符串hello_world        textView.setText(R.string.hello_world);        setContentView(textView);    }

上面这个TextView**引用**了this,也就是MainActivity这个context,所以能访问到全局资源,比如R.string.hello_world。

看一下源码

    @android.view.RemotableViewMethod    public final void setText(@StringRes int resid) {        setText(getContext().getResources().getText(resid));    }

可以看到这句代码可以访问资源,而由于TextView在构造的时候传了this进去,getContext()返回的就是当前的MainActivity。

又例如ImageView也可以这么做

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ImageView imageView = new ImageView(this);        //访问ic_launcher这个图片资源        imageView.setImageResource(R.mipmap.ic_launcher);        setContentView(imageView);    }

这里写图片描述


从这里开始就是收费课程了,30软一个月还蛮便宜的其实

Application 的用途

Application才是真正的全局上下文对象,可以进行组件之间信息共享的桥梁。

在项目里指定一个继承自Application的java类 app

并为两个Activity都指定为程序入口
这里写图片描述

在Main1里通过输入文本对app里面的成员变量dataText进行修改,然后测试Main2中是否能读取到修改后的dataText

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        textView = (TextView) findViewById(R.id.shareText);        textView.setText(((App) getApplicationContext()).getTextData());        editText = (EditText) findViewById(R.id.editText);        button = (Button) findViewById(R.id.btnSave);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                ((App) getApplicationContext()).setTextData(editText.getText().toString());            }        });    }

运行后发现报错了

java.lang.ClassCastException: android.app.Application cannot be cast to com.jackie.coursecontext.App

找了一下原因,是AndroidManifest.xml里面忘记让当前的Application指向我们自定义的app了

修改一下

<application        android:name=".App"        ...

重新运行,Main2中显示的就是之前输入的字符串了


Application 生命周期

重写一下上面App类继承自Application的一些方法

onCreate()//创建时执行onTerminate()//终止时执行onTrimMemory(int level)onLowMemory()onConfigurationChanged(Configuration newConfig)//配置变化时执行

分别给app,Main1,Main2 的周期添加一些Log

10-15 06:36:14.072  24348-24348/com.jackie.coursecontext V/jackie﹕ App Created10-15 06:36:14.088  24348-24348/com.jackie.coursecontext V/jackie﹕ Main1 Created10-15 06:42:02.764  26781-26781/com.jackie.coursecontext V/jackie﹕ App Created10-15 06:42:02.768  26781-26781/com.jackie.coursecontext V/jackie﹕ Main2 Created

可以看到最先执行的是Application的onCreate() 也就是说一些初始化操作放在Application里面是很好的


认识 Android Service

程序有的时候不需要与用户交互,只需要在后台进行一些动作,这时候就可以用service了

启动、停止service的时候无论使用1个intent还是2个,操作的都是同一个service。

startService(new Intent(MainActivity.this, MyService.class));stopService(new Intent(MainActivity.this,MyService.class));

在安卓机上面设置-Apps里面可以看到正在运行的进程,可以看到一些service。

为了便于观察,在自定义service时,重写一下

onStartCommand(Intent intent, int flags, int startId)

这个方法是在service被启动时执行

在里面启动一个线程,循环执行一个正在运行的语句,以便观察

        new Thread(new Runnable() {            @Override            public void run() {                while(true){                    Log.v("jackie","服务正在运行...");                    try {                        sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }).start();
10-15 08:50:01.110    2093-3004/com.jackie.courseservice V/jackie﹕ 服务正在运行...10-15 08:50:01.800    2093-2557/com.jackie.courseservice V/jackie﹕ 服务正在运行...10-15 08:50:02.120    2093-3004/com.jackie.courseservice V/jackie﹕ 服务正在运行...10-15 08:50:02.810    2093-2557/com.jackie.courseservice V/jackie﹕ 服务正在运行...10-15 08:50:03.131    2093-3004/com.jackie.courseservice V/jackie﹕ 服务正在运行...

即使此退出Activity,service也不会停止。

由于这里按钮较多,如果每一个按钮都去写一个OnClickListener() 那么会显得很冗余。可以让这个MainActivity**实现OnClickListener接口(非常重要)**,然后重写当前Activity的OnClick(View v) 通过View的id来区分功能,然后按钮只要绑定当前Activity就行了。

        findViewById(R.id.btnStart).setOnClickListener(this);        findViewById(R.id.btnStop).setOnClickListener(this);        findViewById(R.id.btnBind).setOnClickListener(this);        findViewById(R.id.btnUnBind).setOnClickListener(this);        ...
    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.btnStart:                Log.v("jackie", "开始服务");                startService(new Intent(MainActivity.this, MyService.class));                break;            case R.id.btnStop:                Log.v("jackie","停止服务");                stopService(new Intent(MainActivity.this, MyService.class));                break;            case R.id.btnBind:                Log.v("jackie", "绑定服务");                bindService(new Intent(MainActivity.this, MyService.class), this, BIND_AUTO_CREATE);                break;            case R.id.btnUnBind:                Log.v("jackie", "解绑服务");                unbindService(this);                break;        }    }

如果直接就这样启动的话:会报错

java.lang.RuntimeException: Unable to bind to service

因为onBind() 方法还没有进行重写

    @Override    public IBinder onBind(Intent intent) {        return new Binder();    }

点击绑定服务

10-15 09:20:45.091  15889-15889/com.jackie.courseservice V/jackie﹕ 绑定服务10-15 09:20:45.131  15889-15889/com.jackie.courseservice V/jackie﹕ Service Connected

Service生命周期

这里写图片描述

启动并且绑定服务,如果直接停止服务的话,可以看到,Service并没有destroyed

10-15 09:29:32.380  18152-18152/com.jackie.courseservice V/jackie﹕ 开始服务10-15 09:29:32.408  18152-18152/com.jackie.courseservice V/jackie﹕ Service created10-15 09:29:34.393  18152-18152/com.jackie.courseservice V/jackie﹕ 绑定服务10-15 09:29:34.407  18152-18152/com.jackie.courseservice V/jackie﹕ Service Connected    --------- beginning of system10-15 09:30:06.144  18152-18152/com.jackie.courseservice V/jackie﹕ 停止服务

必须解绑,才会destroyed

10-15 09:31:32.793  18152-18152/com.jackie.courseservice V/jackie﹕ 解绑服务10-15 09:31:32.801  18152-18152/com.jackie.courseservice V/jackie﹕ Service destroyed

如果在已经绑定服务的情况下,直接退出Activity,会报异常

10-15 09:32:52.379  18152-18152/com.jackie.courseservice E/ActivityThread﹕ Activity com.jackie.courseservice.MainActivity has leaked ServiceConnection com.jackie.courseservice.MainActivity@1c2f7e9 that was originally bound here    android.app.ServiceConnectionLeaked: Activity com.jackie.courseservice.MainActivity has leaked ServiceConnection com.jackie.courseservice.MainActivity@1c2f7e9 that was originally bound here

同时,Service会destroy

10-15 09:32:52.384  18152-18152/com.jackie.courseservice V/jackie﹕ Service destroyed

重写一下onStartCommand(Intent intent, int flags, int startId) ,添加一句Log

点击启动服务按钮:

10-15 09:37:35.279  22880-22880/com.jackie.courseservice V/jackie﹕ 开始服务10-15 09:37:35.298  22880-22880/com.jackie.courseservice V/jackie﹕ Service created10-15 09:37:35.298  22880-22880/com.jackie.courseservice V/jackie﹕ Command started

如果重复点击启动服务按钮,可以看到LogCat

10-15 09:37:35.298  22880-22880/com.jackie.courseservice V/jackie﹕ Command started10-15 09:38:41.231  22880-22880/com.jackie.courseservice V/jackie﹕ 开始服务10-15 09:38:41.242  22880-22880/com.jackie.courseservice V/jackie﹕ Command started10-15 09:38:41.650  22880-22880/com.jackie.courseservice V/jackie﹕ 开始服务10-15 09:38:41.653  22880-22880/com.jackie.courseservice V/jackie﹕ Command started10-15 09:38:42.061  22880-22880/com.jackie.courseservice V/jackie﹕ 开始服务10-15 09:38:42.079  22880-22880/com.jackie.courseservice V/jackie﹕ Command started

可见无论怎么点击,onCreate() 都只执行一次,而onStartCommand() 则每点击一次就执行一次。

给MyService添加成员变量private boolean isRunning = false;
并且onCreate()isRunning = true;onDestroy()isRunning = false;

启动/停止服务;

10-15 10:01:37.030      711-711/com.jackie.courseservice V/jackie﹕ 开始服务10-15 10:01:37.034      711-711/com.jackie.courseservice V/jackie﹕ Service created10-15 10:01:37.034      711-711/com.jackie.courseservice V/jackie﹕ Command started10-15 10:01:37.044      711-865/com.jackie.courseservice V/jackie﹕ 服务正在运行...10-15 10:01:39.055      711-865/com.jackie.courseservice V/jackie﹕ 服务正在运行...10-15 10:01:40.218      711-711/com.jackie.courseservice V/jackie﹕ 停止服务10-15 10:01:40.223      711-711/com.jackie.courseservice V/jackie﹕ Service destroyed
0 0
原创粉丝点击