一、Activity是什么

Activity是一种可以包含用户界面的组件,主要用于和用户进行交互。
一个应用可以包含零个或多个Activity。但不包含Activity的应用程序无法被用户看到。

二、Activity的基本用法

1、手动创建Activity

我们可以先创建一个没有Activity的项目,即在创建项目的时候选择“Add No Activity”。
项目名字可以叫做ActivityTest,包名默认为com.example.activitytest。

此时com.example.activitytest这个包是空的,我们需要手动创建一个Activity。
右击这个包 --> New --> Activity --> Empty Activity,我们将其命名为FirstActivity。
在弹出的对话框内有两个选项,勾选Generate Layout File表示自动为FirstActivity创建一个布局文件,勾选Launcher Activity表示会将其设置为当前项目的主Activity。

打开你创建的Activity文件:

class FirstActivity : AppCompatActivity(){override fun onCreate(savedInstanceState: Bundle?){super.onCreat(savedInstanceState);}
}

它已经帮你写好了一个方法,而且这个方法非常简单,就是调用了父类的onCreat方法。

2、创建和加载布局

Android程序设计讲究逻辑和视图分离,最好每一个Activity都对应一个布局。
布局是显示界面内容的,现在手动创建一个布局文件,app/src/main/res目录下先创建一个名为layout的目录,然后在其下建一个Layout resource file的布局文件,命名first_layout,根元素默认选择LinearLayout。

现在first_layout.xml文件中是如下代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent">
</LinearLayout>

由于创建布局选择了LinerLayout作为根元素,因此现在布局文件中已经有一个LinerLayout元素了,现在添加一个按钮元素:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/button1"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="按钮"/></LinearLayout>

Button元素中的属性:

  • android:id : 是给当前的元素定义一个唯一 的标识符(@+id是定义一个id的意思,@id是是引用id)
  • android:layout_width : 指定了当前元素的宽度
  • android:layout_height: 指定当前元素的高度
  • android:text :指定了当前元素中显示的文字内容
  • wrap_content :表示让当前元素只要刚好包含里面的内容
  • match_parent :表示让当前元素和父元素一样宽(高)

可以通过右侧Validation(之前版本是Preview)来预览当前布局。

然后在FirstActivity中加载这个布局:

class FirstActivity : AppCompatActivity(){override fun onCreate(savedInstanceState: Bundle?){super.onCreat(savedInstanceState);setContentView(R.layout.first_layout)}
}

可以看到,这里调用了setContentView()方法来给当前的Activity加载一个布局,参数是布局文件的id,因为项目中的任何资源都会在R文件中生成一个相应的资源id,所以可以通过R.layout.first_layout来获得first_layout.xml布局的id,填入该方法中。

3、在AndroidManifest文件中注册

所有的Activity都需要在AndroidManifest.xml中注册才能生效,Android Studio会自动帮我们完成注册,下面看AndroidManifest文件中的代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.activitytest"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/Apptheam"><activity android:name=".FirstActivity"></activity></application>
</manifest>

在<activity>标签中,android:name来指定具体注册哪个Activity,这里填入的.FirstActivity是com.example.activitytest.FirstActivity,即Activity路径的缩写,因为我们在最外层<manifest>标签通过package属性指定了包名,所以可以省略报名只写.FirstActivity。

如果要想让程序运行,就必须配置主Activity,要想配置主Activity,就在哪个Activity的<activity>标签内加入以下代码,此时的<activity>标签为:

<activity android:name=".FirstActivity"android:label="This is FirstActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter>
</activity>

此处的android:label用来指定Activity中标题栏的内容,如果是主Activity,还会成为启动器中应用程序显示的名称。

现在就可以运行程序了。

4、在Activity中使用Toast

Toast是Android中的一种非常好的提醒方式,就是你经常在各类app中看到的显示在底部的存在一段时间就自动消失的消息,在程序中它可以将一些短小的消息通知给用户,一段时间后自动消失,不会占任何屏幕空间。

在Activity中使用Toast非常简单,首先定义一个弹出Toast的触发点,之前写的程序中写了一个按钮,将其作为触发点来弹出Toast,如下:

override fun onCreate(savedInstanceState: Bundle?){super.onCreat(savedInstanceState);setContentView(R.layout.first_layout)val button1: Button = findViewById(R.id.button1)//导入插件之后这一行就可以不用了button1.setOnClickListener{Toast.makeText(this,"你按了按钮",Toast.LENGTH_SHORT).show()}
}

注意:

  • ① 在Activity中,你可以通过findViewById()方法来获取在布局文件中定义的元素,其返回对象是一个继承自View的泛型对象,Kotlin无法自动推导它是一个什么控件,因此需要将button1显式地定义成Button类型。
  • ② 在Kotlin中引入kotlin-android-extensions插件之后,它就会根据布局文件中定义控件的id自动生成一个具有相同名称的变量,直接调用使用这个变量即可。
  • ③ 得到按钮的实例之后,通过setOnClickListener()方法为其注册一个监听器,点击即会执行监听器中的onClick()方法,弹出Toast的功能就在onClick()方法中编写的了。
  • ④ Toast的用法:通过静态方法makeTest()创建一个Toast对象,然后调用show()方法将其显示出来即可。makeTest()方法中的三个参数:第一个参数是Context,即Toast的上下文,因Activity本身就是一个Context对象,所以传入this即可;第二参数是Toast显示的文本内容;第三个参数是Toast显示的时长,有两个内置变量可以选择:Toast.LENGTH_SHORT和Toast.LENGTH_LONG。

5、在Activity中使用Menu

手机的屏幕控件非常有限,为了充分利用手机屏幕空间,Android提供了一种很不错的解决方式。

首先在res下新建一个menu文件夹,右键点击New->Menu resource file 新建一个叫“main”的菜单文件,然后添加如下代码:

<menu xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:id="@+id/add_item"android:title="Add"/><itemandroid:id="@+id/remove_item"android:title="Remove"/>
</menu>

这里创建了两个菜单项,其中<item>标签用来创建具体的某一个菜单项,然后通过android:id来给这个菜单项指定一个唯一标识符,通过android:title给这个菜单项指定一个名称。

然后回到FirstActivity中来重写onCreateOptionMenu()方法,并且在方法中编写如下代码:

override fun onCreateOptionMenu(menu:Menu?):Boolean{menuInflater.inflate(R.menu.main,menu);return true;
}

这里menuInflater使用了Kotlin中的语法糖,实际上是调用了父类的getMenuInflater()方法,获得一个MenuInflater,再调用其inflate()方法,这样即可给Activity创建菜单。
在inflate()方法中接收两个参数:第一个参数用于指定我们通过哪个资源文件来创建菜单;第二个参数用于指定我们的菜单项将添加到哪个Menu对象中.
最后返回true表示允许我们创建的菜单显示出来,若返回了false,创建的菜单将无法显示。

这时候菜单可以显示了,如果我们想使用这个菜单,就要再定义菜单响应事件:在FirstActicity中重写onOptionsItemSelected()方法,如下:

override fun onOptionsItemSelected(item: MenuItem): Boolen{when(item.itemId){R.id.add_item -> Toast.makeText(this,"你点击了Add",Toast.LENGTH_SHORT).show();R.id.remove_item -> Toast.makeText(this,"你点击了Remove",Toast.LENGTH_SHORT).show();}return true;
}

6、销毁一个 Activity

(1)按一下 Back 键

就按一下返回键就完事了。

(2)通过程序来销毁

调用finish()方法即可:

button1.setOnClickListener{finish()
}

这里点一下按钮就销毁Activity了。

三、使用Intent在Activity中穿梭

Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅可以指明当前组件要执行的动作,还可以在不同组件之间传递数据。

Intent一般可用于启动Activity、启动Service以及发送广播等场景。

Intent大致可分为显示Intent和隐士Intet。

1、使用显式Intent

在上述程序的基础上再创建一个Activity命名为SecondActivity,打开自动生成的second_layout.xml,将里面代码替换成如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/button2"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="另一个按钮"/>
</LinearLayout>

这里还是定义了一个按钮。
此时这个Activity自动在AndroidManifest.xml中注册了,会多如下代码:

<activity android:name=".SecondActivity">
</activity>

下面来看Intent。

Intent有多个构造函数的重载,其中一个是Intent(Content packageContext, Class<?> cls),这个构造函数接收两个参数:第一个参数Content要求提供一个启动Activity的上下文;第二个参数Class用于指定想要启动的目标Activity。
在Activity类中提供了一个startActivity()方法,专门用于启动Activity,它接收一个Intent参数,我们将构建好的Intent传入即可。

修改FirstActivity中按钮的点击事件:

button1.setOnclickListener{val intent = Intent(this, SecondActivity::class.java)startActivity(intent)
}

这样点击FirstActivity中的按钮之后就会跳转到SecondActivity,要想返回的话,按一下Back键即可。

2、使用隐式Intent

相较于显示Intent,隐式Intent并不明确指出想要启动哪个Activity,而是更加抽象地指定了一系列更为抽象的action和category等信息,然后交由系统去分析这个Intent,并找到合适的Activity去启动。

所谓合适的Activity,即可以响应这个Intent的Activity。
通过在<activity>标签下配置<intent-filter>的内容,可指定当前Activity的action和category,打开AndroidManifest.xml,添加代码:

<activity android:name=".SecondActivity"><intent-filter><action android:name="com.example.activitytest.ACTION_START" /><category android:name="android.intent.category.DEFAULT" /></intent-filter>
</activity>

在<action>标签中指定了本Activity可以响应com.example.activitytest.ACTION_START这个action,而<category>标签包含了一些附加信息,更加精确地指明了当前Activity能够响应的Intent可能带有的category。只有当<action>和<category中的内容同时匹配Intent中指定的action和category时,这个Activity才能响应该Intent。

修改First中按钮的点击事件:

button1.setOnClickListener{val intent = Intent("com.example.activitytest.ACTION_START")startActivity(intent)
}

这里提一点,android.intent.category.DEFAULT是一种默认的category,在调用startActivity()的时候会自动添加到Intent中。

Intent添加category的方法如下:

intent.addCategory("这里添加<category>标签中对应的内容")

3、更多隐式Intent的用法

这里举两个,响应网页和电话。

(1)打开网页与响应网页

例如点击按钮打开百度,修改FirstActivity中按钮的点击事件:

button1.setOnClickListener{val intent = Intent(Intent.ACTION_VIEW)intent.data = Uri.parse("https://www.baidu.com")startActivity(intent)
}

这里首先指定了Intent的action是Intent.ACTION_VIEW,这是一个Android系统内置的动作,其常量值为android.intent.action.VIEW。
然后通过Uri.parse()方法将一个网址字符串解析成一个Uri对象,再调用Intent的setData()方法将这个Uri对象传递进去。

与之对应的,我们还可以再/标签中再配置一个/标签用于指定当前Action能够响应的数据。
<data>标签可以配置以下内容:

  • android:scheme:用于指定数据的写一部分,如上例https部分
  • android:host:用于指定数据的主机名部分,如上例www.baidu.com部分
  • android:port:用于指定数据端口部分,一般紧随在主机名后
  • android:path:用于指定主机名和端口之后的部分,如一段网址中跟在用户名之后的部分
  • android:mimeType:用于指定可以处理的数据类型,允许使用通配符的方式指定

只有当<data>标签中指定的内容和Intent中携带的Data完全一致时,该Activity才会响应该Intent。
不过在<data>标签中一般不会指定过多内容。

这里再提一点,Android Studio认为所有能够响应ACTION_VIEW的Activity都应该加上BROWSABLE的category,否则就会给出一段警告提醒。加上BROWSABLE的category是为了实现deep link功能,这里没得学到,所以可以直接再<intent-filter>上使用tools:ignore属性将警告忽略,即改成:\<intent-filter tool:ignore="AppLinkUrlError">

(2)调用系统拨号界面

button1.setOnClickListener{val intent = Intent(Intent.ACTION_DIAL)intent.data = Uri.parse("tel:10086")startActivity(intent)
}

首先指定了Intent的action是Intent.ACTION_DIAL,然后再data部分定义了协议是tel,号码是10086。

4、向下一个Activity传递数据

Intent中提供了一系列putExtra()方法的重载,可以将我们想要传递的数据暂存到Intent中,在启动另一个Activity后再从Intent中取出来即可。

例如传递一个字符串:

button1.setOnClickListener{val data = "你好哇!";val intent = Intent(this,SecondActivity::class.java)intent.putExtra("extra_data", data)startActivity(intent)
}

然后再在SecondActivity中取出:

class SecondActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.second_activity)val extraData = intent.getStringExtra("extra_data")Log.d("SecondActivity", "extra data is $extraData")
}

上述代码中的intent也是调用父类的getIntent()方法获取到Intent。
若传递的是整形数据,则用getIntExtra(),布尔类型则用getBooleanExtra(),以此类推。

5、返回数据给上一个Activity

在Activity类中有一个用于启动Activity的startActivityForResult()方法,它期望Activity销毁的时候能够返回一个结果给上一个Activity。
startActivityForResult()方法接收两个参数:第一个是Intent;第二个是请求码。

例如:

//FirstActivity
button1.setOnClickListener{val intent = Intent(this,SecondActivity::class.java)startActivityForResult(intent, 1)
}

(1)使用按钮调用finish()方法销毁Activity返回

//SecondActivity
class SecondActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.second_activity)button2.setOnClickListener{val intent = Intent()intent.putExtra("data_return", "你也好哇!")setResult(RESULT_OK, intent)finish()}}
}

在SecondActivity中的intent仅仅用于传递数据而已,没有“意图”。
将要传递的数据存入Intent中,然后调用setResult()方法向上一个Activity返回数据。
setResult()方法接收两个参数:第一个参数用于向上一个Activity返回处理结果,一般只使用RESULT_OK或RESULT_CANCELED;第二个参数是带有要传递数据的Intent。
最后调用finish()方法销毁当前Activity。

(2)按下Back销毁Activity返回

通过在SecondActivity抽个血onBackPerssed()方法来实现:

override fun onBackPressed() {val intent = Intent()intent.putExtra("data_return", "你也好哇!")setResult(RESULT_OK, intent)finish()
}

类似

(3)接收返回值

由于我们是使用startActivityForResult()来启动的SecondActivity,所以在其销毁后会回调上一个Activity的onActivityResult()方法:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {super.onActivityResult(requestCode, resultCode, data)when  (requestCode){1 -> if(resultCode == RESULT_OK){val returnData = data?.getStringExtra("data_return")Log.d("FirstActivity", "returned data is $returnData")}}
}

onActivityResult()方法带有三个参数:第一个requestCode是我们在启动Actvity时传入的请求码;第二个resultCode是返回数据时传入的处理结果;第三个data是携带着返回值的Intent。

四、Activity的生命周期

1、返回栈

Android中的Activity是可以层叠的,我们每启动一个新的Activity,就会覆盖到原Activity上,然后点击Back键就会销毁最上层的Activity,下面的Activity就会重新显示出来。

Android是通过任务(task)来管理Activity的,一个任务就是一组存放在栈里的Activity的集合,这个栈也被称为返回栈。
栈是一种先进后出的数据结构,新Activity来了就会压栈,系统总会是显示栈顶的Activity给用户看,而当栈顶的Activity销毁后,会被弹出栈,继续显示栈顶的Activity,即销毁的Activity的下一个Activity。

2、Activity状态

每个Activity在其生命周期中最多可能会有四种状态。

(1)运行状态

当一个Activity位于返回栈的栈顶时,Activity就会处于运行状态。
系统最不愿意回收的就是运行状态的Activity,因为这会带来非常差的用户体验。

(2)暂停状态

当一个Activity不再处于栈顶位置,但仍然可见时就进入了暂停状态,例如弹出的只占用屏幕中间的对话框形式Activity。
处于暂停状态的Activity仍然是完全存活着的,系统也不愿意回收这类Activity,只有在内存极低的情况下才会去考虑回收这类Activity。

(3)停止状态

当一个Activity不处于栈顶位置且完全不可见的时候,就进入了停止状态。
系统仍然会为这种Activity保存相应的状态和成员变量,但这并不是完全可靠的,当其他地方需要内存时,处于停止状态的Activity就可能被系统回收。

(4)销毁状态

一个Activity从返回栈移除后就变成了销毁状态。
系统最倾向于回收处于这种状态的Activity,以保证手机内存的充足。

3、Activity的生存期

Activity类中定义了7个回调方法覆盖了Activity生命周期中的每个环节。

  • onCreat():我们在每个Activity中都重写了这个方法,它会在Activity第一次被创建的时候调用。应该在这个方法中完成Activity的初始化操作,比如加载布局、绑定事件等。
  • onStart():这个方法在Activity由不可见变为可见的时候调用。
  • onResume():这个方法在Activity准备好和用户进行交互的时候调用,此时的Activity一定位于返回栈的栈顶,并且处于运行状态。
  • onPause():这个方法在系统准备去启动或恢复另一个Activity的时候调用。通常在这个方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据,但这个方法执行一定要快,不然会影响到新的栈顶Activity的使用。
  • onStop():这个发给发在Activity完全不可见的时候调用。它和onPause()的区别在于:若启动的新Activity是对话框形式的Activity,那么onPause()会执行,onStop不会执行。
  • onDestory():这个方法在Activity被销毁之前调用,之后Activity的状态将变为销毁状态。
  • onRestart():这个方法在Activity由停止状态变为运行状态之前调用,也就是Activity被重新启动了。

以上七个方法除了onRestart()方法,其他都是两两相对的,从而又可以将Activity分为以下三种生存期:

  • 完整生存期:Activity在onCreat()方法和onDestory()方法之间经历的就是完整生存期。一般情况下,一个Activity会在onCreat()方法中完成各种初始化操作,在onDestory()方法中完成释放内存的操作。
  • 可见生存期:Activity在onStart()方法和onStop()方法之间精力的就是可见生存期。在可见生存期内,Activity对用户总是可见的,即便有可能无法和用户进行交互。可以通过这两个方法合理地管理那些对用户可见的资源。比如在onStart()方法中对资源进行加载,在onStop()方法中对资源进行释放,从而保证处于停止状态的Activity不会占用过多内存。
  • 前台生存期:Activity在onResume()方法和onPause()方法之间所经历的就是前台生存期。在前台生存期内,Activity总是运行状态,此时的Activity是可以和用户进行交互的,我们平时看到的和接触最多的就是这个状态下的Activity。
将Activity设置成对话框式

只需要修改AndroidManifest.xml中的<activity>标签即可。

<activity android:name=".DialogActivity"android:theme="@style/Theme.AppCompat.Dialog">
</activity>

4、Activity被回收了怎么办

当一个Activity进入了停止状态,是有可能被系统回收的。

假如有这么一个场景:应用中有一个Actvity A(这里简称A),在A的基础上启动了Activity B(这里简称B),A就进入了停止状态,这个时候系统内存不足所以将A回收了,接下来用户按下Back键返回A,那么会发生什么问题?
其实还是能够回到A的,但是这个A并不会执行onRestart()方法,而是会执行A的onCreate()方法,因为此时的A会被重新创建一次。但是这里又一个问题,你在A中存储的数据就会不见了,因为A重新创建了。

要想解决这个问题,保存数据,就需要用到Activity中提供的onSaveInstanceState()回调方法。
onSaveInstanceState()方法会携带一个Budle类型的参数,Budle提供了一系列的方法用于保存数据,如使用putString()方法并保存字符串,使用putInt()方法保存整形数据,以此类推。每个保存方法需要传入两个参数,第一个参数是键,用于后面从Bundle中取值,第二个是要保存的内容。

例如添加如下代码,首先是保存数据:

override fun onSaveInstanceState(outState: Bundle){super.onSaveInstanceState(outState)val tempData = "这里是一条数据"outState.putString("key",tempData)
}

获取数据:

override fun onCreate(saveInstanceState: Bundle?){super.onCreat(saveInstanceState)Log.d(tag, "onCreate")setContentView(R.layout.activity_main)if(saveInstanceState != null){val tempData = saveInstanceState.getString("key")Log.d(tag,tempData)}
}

Intent还可以结合Bundle来一起传递数据,首先将数据存到Bundle对象中,再把Bundle对象存入Intent中即可,到了目标Activity之后,先从Intent中取出Bundle,然后再从Bundle中取出数据。

五、Activity的启动模式

在实际项目中我们应该根据特定的需求为每个Activity指定恰当的启动模式。

启动模式一共四种,分别是standard、singleTop、singleTask、singleInstance,可以在AndroidManifest.xml中通过给<activity>标签指定android:launchMode属性来选择启动模式。

1、standard

standard是Activity默认的启动模式,在不进行显示指定的情况下,所有Activity都会自动使用这种启动模式。
Android是使用返回栈来管理Activity的,在standard模式下,每当启动一个新的Activity,他就会在返回栈中入栈,并处于栈顶的位置。对于使用standard模式的Activity,系统并不在乎这个Activity是否已经在返回栈中存在,每次启动都会创建一个该Activity的新实例。

测试standard模式:

override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)Log.d("FirstActivity",this.toString())setContentView(R.layout.first_layout)button1.setOnClickListener{val intent = Intent(this,FirstActivity::class.java)startActivity(intent)}
}

代码是在FirstActivity(简称A)的基础上启动A,从逻辑上来讲,确实没什么意义,但如果你点击两次这个按钮,你会发现控制台上,每当你点击一次按钮,就会创建出一个新的A,此时返回栈中会有三个A实例,也就意味着需要连续按三次Back键才能退出程序。

2、singleTop

当Activity的启动模式指定为singleTop,在启动Activity时如果发现返回栈的栈顶已经是该Activity,则认为可以直接使用它,不会再创建新的Activity实例。

测试singleTop模式,首先修改启动模式:

<activityandroid:name=".FirstActivity"android:launchMode="singleTop"android:label="FirstActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>

重新运行程序后,不管你点多少次按钮,控制台都不会再有新的打印信息出现了,因为目前A已经处于返回栈的栈顶,每当想要启动一个Activity时,都会直接使用栈顶的Activity,因此A只有一个实例,仅按一次Back键即可退出程序。

不过需要注意一点,当A未处于栈顶的情况下,再启动FirstActvity还是会创建新的实例。

3、singleTask

使用singleTop可以很好地解决重复创建栈顶Activity的问题,但是如果Activity不在栈顶,还是可能会创建多个Activity实例。

借助singleTask就可以实现让某个Activity在整个应用程序的上下文只有一个实例。当Activity的启动模式指定为singleTask,每次启动该Activity,系统首先会在返回栈中检查是否存在该Activity的实例,如果发现已经存在则直接使用该实例,并把在这个Actvity之上的所有其他Activity全部出栈,如果没有发现就会创建一个新的实例。

4、singleInstance

singleInstance模式应该算是四种启动模式中最特殊也最复杂的一个了,不同于其他三种启动模式,指定为singleInstance模式的Activity会启用一个新的返回栈来管理这个Activity(若singleTask指定了不同的taskAffinity,也会启动一个新的返回栈)。
假设我们有一个Activity是允许其他Activity调用的,如果想实现其他程序和我们的程序可以共享这个Activity的实例,就可以使用singleInstance模式来实现,在这种模式下,会有一个单独的返回栈来管理这个Activity,不管哪个应用程序来访问这个Activity,都共用同一个Activity,也就解决了共享Activity实例的问题。

Activity基础学习相关推荐

  1. Androidz之Activity概要学习

    Androidz之Activity概要学习 1.     Activity类概述 Activity(活动)是一个单独的.能获取焦点的,且能与用户交互的东西.所以我们通常在Activity类中的onCr ...

  2. Mendix敏捷开发零基础学习《三》-高级 (数据删除保护机制、数据关联删除、Security安全、调用外部接口、调用JAVA代码)

    目录 Mendix敏捷开发零基础学习<三> 一. 数据保护机制(Prevention of Delete) 1.业务需求 2.业务分析 3.项目实现 二.Mendix权限(Security ...

  3. Mendix敏捷开发零基础学习《二》-进阶(Microflow微流、表单验证、运算符、条件判断、数据嵌套、触发器、Debug问题跟踪、版本管理)

    目录结构 Mendix敏捷开发零基础学习<二> 一.Microflow微流 1.引言 2.常见的功能 3.微流可以做那些事情? 3.1 举例1(用微流打开新增页面) 3.2 举例2(用微流 ...

  4. 第7课: bs4 库 的 BeautifulSoup 基础学习

    这里写目录标题 本节课内容所需要安装的 库: BeautifulSoup 简介: lxml 简介: requests ,BeautifulSoup 和 lxml 相互三者关系: 如何利用 bs4 的 ...

  5. 【转】oracle PLSQL基础学习

    [转]oracle PLSQL基础学习 --oracle 练习: /**************************************************PL/SQL编程基础****** ...

  6. python创建对象的格式为_Python入门基础学习(面向对象)

    python基础学习笔记(四) 面向对象的三个基本特征: 封装:把客观事物抽象并封装成对象,即将属性,方法和事件等集合在一个整体内 继承:允许使用现有类的功能并在无须重新改写原来的类情况下,对这些功能 ...

  7. 虚幻引擎虚拟现实开发基础学习教程

    流派:电子学习| MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz 语言:英语+中英文字幕(根据原英文字幕机译更准确)|大小解压后:3.93 GB |时长:5h 15m 了 ...

  8. 动画产业基础学习教程 Rad How to Class – Animation Industry Fundamentals

    如何分类--动画产业基础 大小解压后:6.2G 含课程素材 1920X1080 mp4 语言:英语+中英文字幕(根据原英文字幕机译更准确) 信息: 绘画技巧.解剖学.角色设计.透视和整体讲故事--这门 ...

  9. Blender纹理基础学习视频教程 CGCookie – Fundamentals of Texturing in Blender

    Blender纹理基础学习视频教程 CGCookie – Fundamentals of Texturing in Blender Blender纹理基础学习视频教程 CGCookie – Funda ...

最新文章

  1. 【Interfacenavigation】XML中的字体(27)
  2. (并查集 建立关系)食物链 -- POJ-- 1182
  3. 使用R画桑基图(流程图)
  4. qscrollbar 固定滑块大小_五金模具设计:通用滑块结构形式!模具滑块的设计标准!值得收藏...
  5. 【模板】 全排列 有重复元素的全排列
  6. lnmp应用服务器安装手册
  7. 查看Ubuntu中的ip地址
  8. 长期没有工作是什么感觉?
  9. gitgithub拾遗(一)——git
  10. 经纬度坐标格式批量转换
  11. 思科交换机配置【串口初始配置】
  12. Bada学习-(五)多任务模式
  13. 鸿蒙处理器985相当于内核多少,麒麟985处理器相当于骁龙多少_麒麟985处理器性能测评...
  14. 报名丨2017 GrowingIO 增长大会(北京)
  15. 如何提高SQL语句的能力?
  16. thinkphp6 验证码总是提示不正确
  17. 【2】Kali破解家用WI-FI密码 - WPA/WPA2加密
  18. 数据结构各结构特点(数组、链表、栈、队列、树)
  19. 微信小程序--实现拨打电话功能
  20. 兄弟,不要偷看人家摄像头

热门文章

  1. js 将小数转为科学记数法
  2. C#程序开发范例宝典(第三版)(奋斗的小鸟)_PDF 电子书
  3. HTML+css+javascript面试题
  4. 奇迹MU虚拟机 游戏多开无法登陆和登录错误的问题如何解决?
  5. java 最后的异常_关于java:异常处理尝试没有catch,但最后
  6. JME-java开发3D游戏
  7. 如果我是你~学会站在别人的角度去说话
  8. MySQL数据表中的数据单表查询
  9. 【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.1 效果演示、技术点
  10. Qt之热敏打印机设置