分类目录归档:技术谈

only for coding

Android Activity的生命周期

Andoroid使用了返回栈,所以活动是可以层叠的,并且展示给用户的始终是最后入栈的,销毁的时候也是先销毁栈顶的活动。

简单照着书写了一个程序来体验一下Android Activity的生命周期。写了一个主活动,一个Normal活动和一个Dialog活动。layout就不展示了,需要注意的是DialogActivity在AndroidMainfest注册的时候,我们需要使用android:theme属性如下:

 

MainActivity.java

NormalActivity.java

 

Dialog.java

关注LogCat,当我们点击应用程序的时候,会发现依次执行了onCreate(),onStart(),onResume()方法。当我们点击NormalActivity的时候发现执行了onPause(),onStop()的方法,这是因为NormalActivity把MainActivity是完全覆盖了。因而此时MainActivity处于不可见的状态,onStop()方法就会执行。当我们点击返回键返回的时候便会发现执行了onRestart(),onStart(),onResume()方法。因为onCreate()方法只有第一次建立活动的时候才会调用,因而这次并没有执行。

点击DiaLogActivity会发现只打印了onPause(),这是因为DiaLogActivity并没有完全覆盖MainActivity,所以主活动并没有停止。

 

可能发现在MainActivity中我写了一些与之前不同的语句。这是因为当一个活动进入停止状态后,有可能会因为系统内存不足而被销毁。这样当我们back的时候,Activity将会被重新创建。为了不丢失我们的临时数据,既使活动重新创建也可以显示我们之前保存的数据。 那我们就需要onSaveInstanceState()方法,它携带一个Bundle参数,而Bundle有很多方法用来保存数据。如putString()等。这些方法有两个参数,与putExtra()类似,第一个参数是键值,第二个是真正保存的内容。

这段代码可以保存临时数据。

而这个key字符串虽然保存下来了,但是我们仍需要修改onCreate()方法才可以。onCreate()的参数也是一个Bundle类型,一般我们调用这个方法的时候这个参数均为null,但是一旦我们有保存的临时数据的话,这个参数就会带有之前保存的所有数据。我们在进行取值操作即可。

 

 

没了…

Android Activity间通过Intent进行数据传递

先补一些坑:在之前的blog中我是用ACTION_DIAL直接调用系统内部的拨号面板。其实我们还可以直接打开发短信的面板,甚至直接拨号给联系人。

发短信:

注意smsto以及sms_body均为固定写法。ACTION_SENDTO是打开短信面板。ACTION_SEND则是直接发短信。

直接拨号:

但是需要注意的是,我们这里是直接让系统拨号,这就需要获得系统的安全权限。所以我们在AndroidMainfest.xml中声明应用获得这样的安全权限。

这样我们就可以直接拨号了。暂时填坑结束。

 

以上我们都是用Intent来启动活动,但是Intent的强大还可以在启动活动的过程中传递数据。Intent中提供了一系列putExtra的方法的重载,可以把我们想要传递的数据暂存在Intent中,启动了另一个活动后只需要把这些数据从Intent中取出即可。

putExtra()方法有些类似Python中的字典或者STL的map容器,他接受两个参数,第一个参数是Key,用于后面从Intent中取值,第二个参数是真正要传递的数据。现在我们要在ThirdActivity中将传递数据取出并打印到LogCat中。蒟蒻昨天被ZZ普及了一下LogCat的正确使用姿势。

通过getIntent()方法获取用于启动ThirdActivity的Intent,然后调用getStringExtra()方法传入相应的key,即可得到传递的数据。这样当我们再次启动程序后点击button4的时候就会发现LogCat打印了一行”Hello World”。

上面我尝试的是把数据从上一个活动传递到下一个活动,同样我们也可以把数据返回给上一个活动。因为Activity有一个方法startActivityForResult()专门处理这种情况。它有两个参数,第一个参数为Intent,第二个参数为请求码,主要是为了在后面的回调中判断数据的来源。所以这个请求码必须为唯一值。我们在这里设为1.

现在我们需要修改SecondActivity来添加返回数据的逻辑。

解释一下,我们在这里也使用了个Intent,setResult()方法是专门用于向上一个活动返回数据的,第一个参数是用来向上一个活动返回处理结果,第二个参数则是把带有数据的Intent传递回去。这样当我们销毁了SecondActivity后,FirstActivity便调用onActivityResult()方法,所以我们为了处理数据必须重新这个方法。

 

这样我们就实现了返回数据给上一个活动的目标。但是如果用户没有按Button而是直接返回键的话,我们的数据是无法按照上面的方式返回的。这里我们就需要在SecondActivity中重写 onBackPressed()方法,就依然可以返回数据了。

 

 

 

Android Activity的显示Intent和隐式Intent

昨天晚上把自己上次写的那个简陋APP继续往下写了写。

因为之前的的内容只有一个活动,另外再加上一个菜单。但是对于现在的APP来说,一个应用程序往往都还有很多活动。一般从主活动跳转到其他活动使用的大概就是显式Intent和隐式Intent两种。Intent是Android程序中各组件之间进行交互的重要方式,它不仅可以指明当前活动组件想要执行的动作,还可以在不同组件中传递数据。一般被用来启动活动,服务等。

  • 显式Intent

我们先写一个second_activity_layout的布局文件,把它作为我们第二个活动的布局文件。

可以发现我这里居然又设了一个id为button_2的按钮,但是并没有对程序造成什么影响。因为在活动中我们会具体指定到底引用的是哪个布局文件,所以在不同的布局文件中使用同名id并没有什么影响。就像我们在不同的文件夹里可以写重名的文档一样。

并新建立一个SecondActivity。

接下来在AndroidMainfest.xml中完成注册即可。新加代码:

第二个活动已经完成,但是我们仍然无法在程序中启动它。我们可以在FirstActivity中加入一个新的按钮,并让它的点击事件来启动第二个活动。

Intent有多个构造函数,这里我使用的这个函数Intent(Context packageContext,Class<?> cls)第一个参数是提供一个可以启动活动的上下文,第二个则是指定想要启动的目标活动。Activity类中有一个startActivity()方法,这个方法专门用来启动活动,它接受的是一个Intent的参数。我们把构建好的Intent传入startActivity()就可以启动SecondActivity了。

 

  • 隐式Intent

隐式Intent是指我们并不去指定我们想要启动哪个活动而是通过指定一系列的action,category,data之类的信息,让系统去筛选符合条件的Activity,而这些筛选条件需要我们在<intent-filter>配置。

在这里我们简单的写一个ThirdActivity,来尝试一下隐式Intent调用。在ThirdActivity的注册中,我们需要配置<intent-filter>标签里的内容。

需要注意的是被调用的Activity要有一个带有<intent-filter>并且包含<action>的Activity,设定它能处理的Intent,并且category设为”android.intent.category.DEFAULT”。这是一种默认的category,必须添加的。action的name是一个字符串,可以自定义,这个字符串中千万不能有空格教训啊!!但是因为这个Activity也可以被其他应用程序调用,只要有这个action字符串即可,所以为了防止应用程序互相影响,一般命名方式是包名+Action名.这里我只是为了方便所以直接写了ACTION_START。一个Intent只能指定一个action但是我们却可以添加多个category来更精确。

现在我们在FirstActivity中在添一个按钮。

现在我们也可以通过button4来启动第三个活动啦~

当然以上我们都是启动自己程序内的活动,但就像我之前说的只要Action字符串匹配我们也可以调用其它程序的活动。比如安卓系统自带的浏览器和拨号等等。。

我们接下来尝试一下通过这个丑陋的APP来打开百度一下手机没翻墙= =

在FirstActivity再加一个按钮控件,并进行设置,代码如下:

在这里我们指定Intent的action是Intent.ACTION_VIEW,这是一个安卓系统内置的动作即显示用户的数据。setData()接受一个Uri对象,主要用于指定当前Intent正在操作的数据,而Uri.parse()方法是将一个网址的字符串解析成一个Uri对象。这样上面的代码便可以为我们百度一下啦。http则是一种Intent的协议,还有类似的协议比如tel表示拨打电话,geo显示地理位置等等。

手机最重要的还是要拨号吧,有时候可能忘记了某个重要人物的号码,我们也可以为这个APP加上打开拨号面板的功能。

与上面的百度一下类似,Intent.ACTION_DIAL是一种安卓系统内置的动作,打开拨号面板,然后data部分指定了协议是tel,号码是10086.这样拨号面板这个Action也被我们这个辣鸡APP调用了。。。

但是如果有两个活动都符合我们<action>和<category>的筛选条件该怎么办呢?系统就会以对话框列表的方式让用户进行选择。

总结起来就是:每个Intent中只能指定一个action,但却能指定多个category;类别越多,筛选条件越多,那么动作也就更加精确,调用的活动才不会与我们的预期出现大的差别。就先写到这里吧~其实还有很多地方需要注意回来继续学习补坑。