(一)、创建Activity:
1、继承于Activity或其子类,重写onCreate()方法。
2、Activity的注册配置:
注册配置的核心代码:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN" />
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".HeadpicActivity"
android:label="@string/title_activity_headpic" >
</activity>
</application>
3、启动活动:
- 在Android应用里各组件之间通信使用Intent。一个Activity通过Intent来表达自己的“意图”。
- 常用有两种方式:
1.Intent intent =new Intent(MainActivity.this,NextActivity.class);
2.Intent intent=new Intent();
intent.setclass(MainActivity.this,NextActivity.this);
3、常用启动方式有两种:
- startActivity();
- startActivityForResult();
(二)、Activity之间交换数据:
第一种方式:
第二种方式:【常用】
- 甲页面利用intent对象的putExtra()方法传值,乙页面利用getStringExtra()、getIntExtra()等系列方法来一一接收值;
- 甲页面利用bundle对象来保存所有需要传递的数值,通过intent的putExtras()方法传值,乙页面利用intent对象的getExtras()方法返回bundle对象,将所有接收的数据放在bundle对象中,利用bundle的get系列方法一一去除数据。
【备注:】如果甲页面使用putExtras()方法传值,则乙页面使用getExtras()接收值。如果甲页面使用putExtra()方法传值,则乙页面要使用getBundleExtra()方法接收值。
使用intent传输数据有一个限制,我查阅资料看到intent传输的数据最多大概只有512k...所以传输大数据的时候用intent还是不可行的
EG:
//传递一般数据MainAcitvity.java
publicvoid clickButton(View view) {
switch (view.getId()) {
case R.id.button_main_tonext:
Intent intent = new Intent(MainActivity.this, NextActivity.class);
Bundle bundle = new Bundle();
bundle.putString("myname", "xqy");
bundle.putInt("age", 22);
intent.putExtras(bundle);
startActivity(intent);
break;
}
}
//接受一般数据NextAcitvity:
@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
// 接收第一个页面的传值
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String name = bundle.getString("myname");
int age = bundle.getInt("age");
this.setTitle(name + ":" + age);
}
传递对象数据的核心代码:
Person对象核心代码:
public class Personimplements Serializable {
private String userName;
private int age;
private int sex;
private List<String> infoList;
public List<String> getInfoList() {
return infoList;
}
public void setInfoList(List<String> infoList) {
this.infoList = infoList;
}
public String getUserName() {
return userName;
}
publicvoid setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
publicvoid setAge(int age) {
this.age = age;
}
publicint getSex() {
returnsex;
}
publicvoid setSex(int
this.sex = sex;
}
}
MainActivity页面:
public class MainActivity extends Activity {
private Person person = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
person = new Person();
person.setUserName("wangxiangjun");
person.setAge(40);
person.setSex(1);
person.setInfoList(list);
}
public void clickButton(View view) {
switch (view.getId()) {
case R.id.button_main_submit:
Intent intent = new Intent(MainActivity.this,
ReceiverActivity.class);
Bundle bundle = new Bundle();
bundle.putSerializable("person", person);
intent.putExtras(bundle);
startActivity(intent);
break;
}
}
ReceiverActivity页面:
public class ReceiverActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_receiver);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
// 接收Serializable对象
Person data = (Person) bundle.getSerializable("person");
setTitle(data.getUserName() + ":" + data.getAge() + ":"
+ data.getInfoList());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.receiver, menu);
return true;
}
}
第三种方式:借助类的静态变量来实现
由于类的静态成员可以通过“className.fileName”来访问,故而可以供两个Activity访问从而实现Activity之间的数据通信:
public class SecondActivity extends AppCompatActivity {
//声明为静态file
static int age = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
//在MainActivity中更改了age,所以这里肯定不是"1"
Toast.makeText(this, "在MianActivity中更改了age后的值 = " + age, Toast.LENGTH_SHORT).show();
}
}
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//先查看一下未更改的值
SecondActivity.age = 23;
Button btn = (Button) findViewById(R.id.button);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//到SecondActivity中查看对age更改是否有效
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
第四种方式:借助全局变量来实现/Application
和类的静态变量类似,但是这个类作为单独第三个类(最好是写一个Application类):
public class ForExampleClass {
//此处声明一个public static 成员来实现数据通信
public static int age = 0;
}
//在一个Activity中对类的静态变量进行访问和更改:
//先查看一下未更改的值
Toast.makeText(this, "age = " + ForExampleClass.age, Toast.LENGTH_SHORT).show();
//在一个Activity中对类的静态变量进行变更
ForExampleClass.age = 23;
//另外一个activity
//然后在另一个Activity中访问该变量,来验证这种通信方式:
//在另一个Activity中访问更改后的变量来验证
Toast.makeText(this, "更改后的age = " + ForExampleClass.age, Toast.LENGTH_SHORT).show();
其实上边“(四)借助类的静态变量来实现”和“(三)借助全局变量来实现”很类似,只是在借助类的静态变量时接收信息的Activity中声明静态file,在别的Activity中做更改,而借助全局变量(建议继承Application,此时就是所谓的“使用Application”,因为Application类在本应用所有Activity中都可以访问,但是要注意内存泄漏的问题)是另外声明一个类,所有Activity共享这个类而已
第五种方式:
借助外部存储来实现通讯(使用SharedPreference实现Activity之间的数据通信)
可以看我关于SharedPreference的使用博客~~
不足之处在于——从SharedPreference的API就可以看出,采用SharedPreference只能存取标准数据类型的变量值int、float、long、boolean、String。对与一些复杂类型的就捉襟见肘了。
第六种方式:
使用SQLite来实现数据共享通信
可以看我关于SQLite的使用博客~~
第七种方式:
直接使用File来实现
其实从本质属性来讲,使用SharedPreference和SQLite来存取数据都是使用File来存取数据的方式——SharedPreference是存放在data/data/应用包名/shared_prefs目录下后缀为.xml的文件,SQLite是存放在data/data/应用包名/databases目录下的后缀为.db3的文件。只是Android系统为这些文件存取专门格式化了存取格式而已,本质上还是文件读写。
当然,如果你足够淡定,也可以用赤裸裸的File来存储。如果这个文件存在手机私有目录下,那就内部使用,放在SD卡上,那就可以所有应用,一切分享。但是这样暴力的方式需要你在文件读写时进行大量的额外工作。
基于这样外部存储的数据传输,优缺点显而易见,它解决了困扰Intent的传输路径复杂,不利于传输大批量数据的问题,但同时,它有留下了效率隐患,复杂了编程模型。因为面对外部存储,开发者必须要考虑效率问题,很多时候,多线程就会被提上议程,这样,想不麻烦,都不行鸟。
第八种方式:
借助Service来实现
既然存在外部太慢,那么还是在内存级别解决问题好了,这时候,你可能就需要请出Android四大组件之一的Service了。Service设计的本意,就是提供一些后台的服务,数据存取,也可以归于其职责的一部分。
Service是提供了直连机制,调用的Activity,可以通过bindService方法,与目标Service建立一条数据通路,拿到IBinder。这样,通过Android提供的IPC模型(进程间通信),就可以进行远程方法的调用和数据的传输了。
通过这种模式,可以解决一定问题,但是对于Service来说,实在是太大才小用了,Service的专长,不是在数据,还是在逻辑。对于传数据而言,Service还是重量了一点,不但是有连接耗精力,传输经由IPC,写起来也够费劲。而且作为组件,Service随时可能死掉,你还是要费劲心机的处理数据的持久化,得不偿失。
参考博客:https://blog.csdn.net/cyanchen666/article/details/81982562
(三)Activity——调用另一个Activity并返回结果
1、概念:
甲页面调用乙页面,当用户在乙页面完成任务后,程序自动返回到甲页面,而甲页面必须能够获取到用户在完成乙页面后传递的数据结果。
2、做法:
与普通的页面交换数据不同的是,要使用startActivityForResult()方法来启动另一个Activity。
3、示例代码:
1、MainActivity页面:
public class MainActivity extends Activity {
private ImageView imageView_main_headpic;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView_main_headpic = (ImageView) findViewById(R.id.imageView_main_headpic);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
returntrue;
}
publicvoid clickButton(View view) {
switch (view.getId()) {
case R.id.button_main_selectpic:
Intent intent = new Intent(MainActivity.this, HeadpicActivity.class);
startActivityForResult(intent, 0);
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 0 && resultCode == 1) {
Bundle bundle = data.getExtras();
int imgid = bundle.getInt("imgId");
imageView_main_headpic.setImageResource(imgid);
}
}
}
2、NextActivity页面:
public class HeadpicActivity extends Activity {
private GridView gridView_headpic_show;
// 定义数据源
privateint[] imgIds = newint[] { R.drawable.img01, R.drawable.img02,
R.drawable.img03, R.drawable.img04, R.drawable.img05,
R.drawable.img06, R.drawable.img07, R.drawable.img08,
R.drawable.img09 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_headpic);
gridView_headpic_show = (GridView) findViewById(R.id.gridView_headpic_show);
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
for (int i = 0; i < imgIds.length; i++) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("headpic", imgIds[i]);
map.put("picname", "头像—" + i);
list.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(this, list,
R.layout.item_gridview_headpic, new String[] { "picname",
"headpic" }, newint[] {
R.id.text_item_gridview_picname,
R.id.imageView_item_gridview_headpic });
gridView_headpic_show.setAdapter(adapter);
gridView_headpic_show.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent intent = getIntent();
Bundle bundle = new Bundle();
bundle.putInt("imgId", imgIds[position]);
intent.putExtras(bundle);
setResult(1, intent);
finish();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.headpic, menu);
return true;
}
}
(四)Activity生命周期
1.Activity的四种状态:
1.运行状态
当一个活动位于返回栈的栈顶的时候,用户点击屏幕,屏幕会给予响应。这个活动就处于运行状态。
2.暂停状态
当一个活动不再处于栈顶的位置,但是仍然可见的时候(失去焦点),活动不能和用户交互,这个活动处于暂停状态。只有在内存极低的情况下,系统才会考虑去回收这种活动。
3.停止状态
活动不再属于栈顶位置,并且完全不可见的时候,eg:活动被另一个活动完全覆盖的时候,这个活动处于销毁状态。当其他地方需要内存的时候,停止状态的活动有可能被系统回收。
4.销毁状态
当一个活动被返回栈中移除之后就变成销毁状态。系统会最倾向于回收这种状态的活动,从而保证手机的内存充足。
2.Activity的生命周期
当另外一个活动来到前台:
关于生命周期的具体应用场景我在下一篇博客说明
(五)android进程优先级
Android 中,同一个应用的所有组件在默认情况下都运行在同一个进程中,但也可以通过修 改 manifest 文件中的 android:process 属性来指定该组件要运行中那个进程,也可以让不 同应用的组件们运行在同一个进程中,当然这些应用要共享一个用户 ID 并并且有相同的数 字证书。
前台/可见(用户不可点击)/服务/后台/空(可随时被杀掉)
1、前台进程 :
用户当前正在做的事情需要这个进程。如果满足下面的条件之一,一个进程就被认为是前台 进程: 这个进程拥有一个正在与用户交互的 Activity(这个 Activity 的 onResume()方法被调用)。 这个进程拥有一个绑定到正在与用户交互的 activity 上的 Service。 这个进程拥有一个前台运行的 Service(service 调用了方法 startForeground()). 这个进 程拥有一个正 在执行其 任何一个生命 周期回调 方法( onCreate(),onStart(),或 onDestroy())的 Service。 这个进程拥有正在执行其 onReceive()方法的 BroadcastReceiver。
通常,在任何时间点,只有很少的前台进程存在。它们只有在达到无法调合的矛盾时才会被 杀--如内存太小而不能继续运行时。通常,到了这时,设备就达到了一个内存分页调度状 态,所以需要杀一些前台进程来保证用户界面的反应
2、可见进程
一个进程不拥有运行于前台的组件,但是依然能影响用户所见。满足下列条件时,进程即为 可见: 这个进程拥有一个不在前台但仍可见的 Activity(它的 onPause()方法被调用)。当一个前台 activity 启动一个对话框时,就出了这种情况。
3、服务进程
一个可见进程被认为是极其重要的。并且,除非只有杀掉它才可以保证所有前台进程的运行, 否则是不能动它的。 这个进程拥有一个绑定到可见 activity 的 Service。 一个进程不在上述两种之内,但它运行着一个被 startService()所启动的 service。 尽管一个服务进程不直接影响用户所见,但是它们通常做一些用户关心的事情(比如播放音 乐或下载数据),所以系统不到前台进程和可见进程活不下去时不会杀它。
4、后台进程
一个进程拥有一个当前不可见的 activity(activity 的 onStop()方法被调用)。 这样的进程们不会直接影响到用户体验,所以系统可以在任意时刻杀了它们从而为前台、可 见、以及服务进程们提供存储空间。通常有很多后台进程在运行。它们被保存在一个 LRU(最 近最少使用)列表中来确保拥有最近刚被看到的 activity 的进程最后被杀。如果一个 activity 正确的实现了它的生命周期方法,并保存了它的当前状态,那么杀死它的进程将不会对用户 的可视化体验造成影响。因为当用户返回到这个 activity 时,这个 activity 会恢复它所有的可 见状态。