在一个Activity的java程序中,具体看问题描述?

Python019

在一个Activity的java程序中,具体看问题描述?,第1张

1、Intent

Intent是各个组件之间交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,而且还能在各组件之间传递数据。Intent一般可用于启动Activity、启动Service、发送广播等场景。

Intent大致可分为2中:

1、显示Intent

2、隐式Intent

1.1、显示Intent打开Activity

fun openActivity(){

val intent = Intent(this, KotlinFirstActivity::class.java)

intent.putExtra("param", "testParams")

startActivity(intent)

}

注意:KotlinFirstActivity::class.java就相当于Java中的KotlinFirstActivity.class。

1.2、隐式Intent打开程序内的Activity

相比于显示Intent,隐式Intent并不指明启动那个Activity而是指定了一系列的action和category,然后交由系统去分析找到合适的Activity并打开。

什么是合适的Activity,其实就是和隐式Intent中指定的action和category完全匹配的Activity,而action和category我们可以在AdnroidManifest中指定。

在标签中配置了action和category,只有和隐式Intent中的action和category完全匹配才能正常的打开该页面。

val intent = Intent("com.example.abu.alertdialogdemo.ACTION_START")

startActivity(intent)

不是说action和category要完全匹配才能打开页面吗?这是因为android.intent.category.DEFAULT是一种默认的category,在调用startActivity()时会自动将这个category添加到Intent中。所以在Manifest中一定不要忘记配置这个默认的category:android.intent.category.DEFAULT,否则会报错。

还有一点需要注意:Intent中只能添加一个action,但是可以添加多个category。

1.3、隐式Intent打开程序外的Activity

比如我们要打开系统的浏览器

fun openWeb(view: View) {

val intent = Intent(Intent.ACTION_VIEW)

intent.data = Uri.parse("https://www.baidu.com")

startActivity(intent)

}

Intent.ACTION_VIEW是系统内置的动作,然后将https://www.baidu.com通过Uri.parse()转换成Uri对象,传递给intent.setData(Uri uri)函数。Kotlin中intent.data=Uri.parse("https://www.baidu.com")就相当于Java中的intent.setData(Uri.parse("https://www.baidu.com")),这是Kotlin中的语法糖。

与此对应在标签中配置一个标签,用于更精确的指定当前Activity能够相应的数据。标签中主要可以配置一下内容:

1、android:scheme:用于指定数据的协议部分,如https

2、android:host:用于指定数据的主机名部分,如www.baidu.com

3、android:port:用于指定数据的端口,一般紧随主机名后

4、android:path:用于指定数据的路径

5、android:mimeType:用于指定支持的数据类型

只有当标签中指定的内容和Intent中携带的data完全一致时,当前Activity才能响应该Intent。下面我们通过设置data,让它也能响应打开网页的Intent。

我们在ThirdActivity的中配置当前Activity能够响应的action是Intent.ACTION_VIEW的常量值,而category指定了默认的category值,另外在标签data中我们通过android:scheme="https"指定了数据的协议必须是https。另外由于AndroidStudio认为能够响应ACTION_VIEW的Activity都应该加上BROWSABLE的category,否则会报出警告。加上BROWSABLE的category是为了实现deep link 功能和目前学习无关,所以我们在intent-filter标签上添加tools:ignore="AppLinkUrlError"忽略警告。

然后我们就能通过隐式Intent的方法打开ThirdActivity了,代码如下:

val intent= Intent(Intent.ACTION_VIEW)

intent.data=Uri.parse("https:")

startActivity(intent)

除了指定android:scheme为https我们也能随意指定它的值,只需要保证AndroidManifest中设置的值和Intent中设置的data相对应即可。

2、Activity的生命周期

Activity类中定义了7个回调方法,覆盖了Activity声明周期的每一个环节。

1、onCreate(): 在Activity第一次创建时调用

2、onStart():在Activity可见但是没有焦点时调用

3、onResume():在Activity可见并且有焦点时调用

4、onPause():这个方法会在准备启动或者恢复另一个Activity时调用,我们通常在该方法中释放消耗CPU的资源或者保存数据,但在该方法内不能做耗时操作,否则影响另一个另一个Activity的启动或恢复。

5、onStop():在Activity不可见时调用,它和onPause主要区别就是:onPause在失去焦点时会调用但是依然可见,而onStop是完全不可见。

6、onDestory():在Activity被销毁前调用

7、onRestart():在Activity由不在栈顶到再次回到栈顶并且可见时调用。

为了更好的理解Activity的生命周期,看下图

Activity生命周期.png

3、体验Activity的生命周期

下面我们通过实例更直观的看下Activity的生命周期过程。

1、打开FirstActivity,生命周期过程如下

FirstActivity onCreate

FirstActivity onStart

FirstActivity onResume

2、在FirstActivity中打开SecondActivity,生命周期过程如下

FirstActivity onPause

SecondActivity onCreate

SecondActivity onStart

SecondActivity onResume

FirstActivity onStop

可以看到在打开SecondActivity时FirstActivity的onPause会执行,所以在onPause中是不能做耗时操作的,否则会影响SecondActivity的打开。

3、按返回键回到FirstActivity,生命周期过程如下

SecondActivity onPause

FirstActivity onRestart

FirstActivity onStart

FirstActivity onResume

SecondActivity onStop

SecondActivity onDestroy

可以看到在返回FirstActivity时会调用SecondActivity的onPause,如果SecondActivity的onPause中做了耗时操作的话,那么也会影响Activity的返回。而且当FirstActivity再次回到栈顶时会调用其onRestart,此时并不会执行onCreate因为FirstActivity并没有销毁。

4、Activity被回收了时的生命周期

现在描述一种场景:打开ActivityA,然后在ActivityA的页面中打开ActivityB,此时ActivityA不在栈顶了如果内存不足可能会被回收,此时从ActivityB再回到ActivityA,下面描述下整个过程的生命周期。

1、打开ActivityA,执行的生命周期

ActivityA onCreate

ActivityA onStart

ActivityA onResume

2、打开ActivityB执行的生命周期

ActivityA onPause

ActivityB onCreate

ActivityB onStart

ActivityB onResume

ActivityA onStop

3、此时因内存不足,导致ActivityA被回收了,并返回ActivityA

ActivityA onDestory

ActivityB onPause

ActivityA onCreate

ActivityA onStart

ActivityA onResume

ActivityB onStop

从上面可以看出在ActivityA被回收后再次回到ActivityA时不再调用ActivityA的onRestart了,而是调用了ActivityA的onCreate,因为ActivityA已经被销毁了。

5、Activity被销毁,其中的临时数据怎么办

ActivityA被销毁了,这也就说明其中的临时数据也会丢失了,比如ActivityA中有一个EditText,我们在其中输入了一段文字,然后启动ActivityB,此时由于内存紧张处于停止状态的ActivityA被回收了,返回到ActivityA你会发现EditText中输入的文字不见了,因为ActivityA重新创建了。

为此Activity提供了onSaveInstanceState方法,该方法能确保在被回收之前被调用,我们就能在onSaveInstanceState方法中进行临时数据的保存,然后我们可以在onCreate(savedInstanceState: Bundle?)中利用savedInstanceState进行数据的恢复。Activity被回收重新创建时onCreate(savedInstanceState: Bundle?)中的savedInstanceState不再为null否则为null,其中带有在savedInstanceState中保存的所有数据。

具体代码如下:

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

Log.e("tag", "$tag onCreate")

//恢复数据

val tempData = savedInstanceState?.getString("data") ?: ""

et.setText(tempData)

}

//保存数据

override fun onSaveInstanceState(outState: Bundle?) {

super.onSaveInstanceState(outState)

Log.e("tag", "$tag onSaveInstanceState")

val tempData = et.text.toString().trim()

outState?.putString("data", tempData)

}

6、onSaveInstanceState()调用时机

1、用户按下HOME键

2、长按HOME键进入其他程序

3、按下电源键关闭屏幕

4、从ActivityA跳转到一个新的Activity

5、屏幕方向切换时,如从竖屏变成横屏

总而言之,onSaveInstanceState()是在你的Activity有可能在未经允许的情况下被回收时调用,Activity被销毁之前onSaveInstanceState()肯定会被触发,我们可以onSaveInstanceState()中保存临时数据,持久化的数据可以在onPause()中保存。

另外,虽然屏幕方向切换时,会造成Activity的重建会调用onSaveInstanceState(),但是不建议使用onSaveInstanceState()进行数据的保存,我们可以禁止屏幕的旋转或禁止屏幕旋转时Activity的重建。

禁止屏幕旋转

可以在Mainifest中设置屏幕固定为竖屏

android:screenOrieritation="portrait"

禁止屏幕旋转时Activity的重建

android:configChanges="orientation丨keyboardHidden丨screenSize"

7、Activity的启动模式

启动模式分为4种:

1、standard

2、singleTop

3、singleTask

4、singleInstance

我们可以在Manifest中通过android:launchMode指定启动模式。

7.1、standard模式

如果不显示指定启动模式,那么Activity的启动模式就是standard,在该模式下不管Activity栈中有无该Activity,均会创建一个新的Activity并入栈,并处于栈顶的位置。

7.2、singleTop模式

1、要启动的Activity位于栈顶

在启动一个ActivityA时,如果栈顶的Activity就是ActivityA,那么就不会重新创建ActivityA,而是直接使用,此时并不会调用ActivityA的onCreate(),因为并没有重新创建Activity,ActivityA的生命周期如下:

ActivityA onPause

ActivityA onNewIntent

ActivityA onResume

可以看到调用了onNewIntent(intent: Intent?),我们可以在onNewIntent(intent: Intent?)中通过intent来获取新传递过来的数据,因为此时数据可能已经发生了变化。

2、要启动的Activity不在栈顶

虽然我们指定了ActivityA的启动模式为singleTop,但是如果ActivityA在栈中但是不在栈顶的话,那么此时启动ActivityA的话会重新创建一个新的ActivityA并入栈,此时栈中就有2个ActivityA的实例了。

7.3、singleTask模式

如果准备启动的ActivityA的启动模式为singleTask的话,那么会先从栈中查找是否存在ActivityA的实例:

场景一、如果存在则将ActivityA之上的Activity都出栈,并调用ActivityA的onNewIntent()。

场景二、如果ActivityA位于栈顶,则直接使用并调用onNewInent(),此时和singleTop一样。

场景三、 如果栈中不存在ActivityA的实例则会创建一个新的Activity并入栈。

场景一:ActivityA启动ActivityB,然后启动ActivityA,此时生命周期过程:

ActivityB onPause

ActivityA onRestart

ActivityA onStart

ActivityA onNewIntent

ActivityA onResume

ActivityB onStop

ActivityB onDestroy

此时ActivityA不在栈顶,ActivityA之上有ActivityB,所以在启动ActivityA时ActivityA之上的ActivityB会出栈,ActivityA将置于栈顶,所以ActivityA的onRestart和ActivityB的onDestory会执行。

场景二:ActivityA启动ActivityA,此时生命周期过程:

ActivityA onPause

ActivityA onNewIntent

ActivityA onResume

此时ActivityA位于栈顶,此时singleTask和singleTop作用一样,都是直接使用ActivityA,并且会调用ActivityA的onPause、onNewIntent、onResume。

场景三:ActivityA启动ActivityB,此时生命周期过程:

ActivityA onCreate

ActivityA onStart

ActivityA onResume

7.4、singleInstance模式

不同于另外3个模式,指定singleInstance模式的Activity会启动一个新的返回栈来管理这个Activity(其实如果singleTask模式指定了不同的taskAffinity,也会启动一个新的返回栈),这么做的意义是什么?

想象一个场景:如果我们程序内的一个Activity是允许其他程序访问的,如果想实现其他程序和我们程序能共享这个Activity实例,该怎么实现呢?使用前面3中模式是无法做到的,因为每个应用程序都有自己的返回栈,同一个Activity在不同返回栈中肯定都创建了新的实例,而使用singleInstance就可以解决这个问题。在这种模式下,会有一个单独的返回栈来管理这个Activity,无论哪个应用程序来访问这个Activity,都在同一个返回栈中,也就解决了共享Activity实例的问题。

为了更好的理解下面我们实战一下:

1、将ActivityB的启动模式修改为singleInstance

android:name=".ActivityB"

android:launchMode="singleInstance" />

2、在ActivityA、ActivityB、ActivityC的onCreate中打印taskId

##ActivityA

val tag = javaClass.simpleName

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

Log.e("TAG", "$tag taskId=$taskId")

}

##ActivityB

val tag = javaClass.simpleName

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(activity_second)

Log.e("TAG", "$tag taskId=$taskId")

}

##ActivityC

val tag = javaClass.simpleName

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(activity_c)

Log.e("TAG", "$tag taskId=$taskId")

}

在Kotlin中javaClass是当前实例的Class对象,相当于Java的getClass().

在Kotlin中ActivityB::class.java是获取ActivityB类的Class对象,相当于Java中的ActivityB.class。

3、启动ActivityA->启动ActivityB->启动ActivityC,taskId打印结果如下:

ActivityA taskId=4163

ActivityB taskId=4164

ActivityC taskId=4163

可以看到ActivityB的taskId是不同于ActivityA 和ActivityC的,这也说明了ActivityB 是在一个单独的栈中的,并且返回栈中只有这一个Activity。

4、在ActivityC中按返回键,返回到ActivityA,再按返回键返回到ActivityB,这是为什么呢?其实很好理解:ActivityA 和ActivityC 在同一个返回栈中,在ActivityC 中按返回键ActivityC 出栈,此时ActivityA就位于栈顶了,ActivityA就展示在界面上了,在ActivityA中再按返回键,这是当前的返回栈已经空了,于是就展示了另一个返回栈栈顶的ActivityB了。

————————————————

版权声明:本文为CSDN博主「保瓶儿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_31211457/article/details/114052641

有些兼容有些不兼容,可以找破解的竖类游戏。

1.像E6就可以支持横竖的手机。

2.N GAGE游戏的话,利用横屏补丁可以玩一些。

3.现在横屏的游戏很多啊。可以去E63论坛下载。有部分竖屏游戏可以完美自适应横屏幕显示,有部分游戏中间显示,两测是黑边。

希望对你有帮助,谢谢采纳。

这个很简单的,

下载游戏的时候看游戏说明能不能支持竖屏游戏,

因为E63手机是不支持重力感应的

有介绍的就可以竖着玩

不能竖着的那也没办法