全局变量
C/C++有所谓的全局变量,因为全局变量保存在内存中,所以操作全局变量就是操作内存,其速度远比操作数据库或者操作文件快得多,而且工程里的任何代码都可以引用全局变量,因此很多时候全局变量是共享数据和消息传递的好帮手。不过Java没有全局变量的概念,与之比较接近的东西,是类里面的静态成员变量;该变量可被外部直接引用,并且在不同地方引用的值都是一样的(前提是在引用期间不能修改该变量的值)。所以我们可以借助静态成员变量来实现全局变量的功能。
Application组件
Application是比Activity高级的组件,它的生命周期覆盖了APP运行的全过程;而Activity页面的生命周期很短暂,只要进入别的页面,原页面就被停止或者销毁;因此我们可以在Application中保存全局变量。在打开App时,系统会先初始化Application,然后才进入到开始的Activity页面。通常我们不需要指定一个Application,这时系统会自动帮我们创建,如果需要创建自己的Application,创建一个派生自Application的类,并在manifest的application标签中注册就好了。
适合在Application中保存的全局变量,主要是一些Activity不方便传输的对象,包括:
1、Java容器类和需要使用方法的对象;因为Intent不能直接传递容器数据,同时序列化对象只能传输数据却不能传输方法。
2、多个Activity都要使用的数据,比如说电商APP的用户信息,既不方便在每次Activity跳转时都传递用户数据,也不方便在每个Activity页面频繁查询用户数据库,所以这种数据也适合作为全局变量由Application管理。
3、容易因频繁分配内存而导致内存泄漏的对象,如Handler对象。
Application内存读写的实现思路
首先写一个类MainApplication继承自Application,该类要采用单例模式,内部声明自身类的一个静态成员对象,在创建app时把自身赋值给这个静态对象,然后提供一个静态对象的获取方法。
其次在每个Activity中声明MainApplication类的成员对象,同时获取MainApplication的静态对象赋值给该成员对象,于是每个Activity都持有了MainApplication的唯一实例,保证它们操作的都是同一套东西。
接着在具体Activity中,就可以通过该成员对象访问MainApplication内部的公共对象和公共方法了。
最后不要忘了在AndroidManifest.xml中注册新定义的Application类名,即在application节点中增加android:name属性。Android工程默认没有该属性,如果不设置该属性,系统会启用默认的Application,当然此时我们就无法实现全局变量了。
下面是具体的代码例子
MainApplication的代码
import java.util.HashMap;
import java.util.Map;
import android.app.Application;
public class MainApplication extends Application {
private static MainApplication mApp;
public HashMap<String, String> mMap = new HashMap<String, String>();
public static MainApplication getInstance() {
return mApp;
}
@Override
public void onCreate() {
super.onCreate();
mApp = this;
}
public String getMapDesc() {
String desc = "键值对信息如下:\n";
for (Map.Entry<String, String> item_map : mMap.entrySet()) {
desc = String.format("%s字段名称:%s,字段值:%s\n",
desc, item_map.getKey(), item_map.getValue());
}
return desc;
}
}
主页面的代码
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private MainApplication mApp = MainApplication.getInstance();
private EditText et_key, et_value;
private TextView tv_desc;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_key = (EditText) findViewById(R.id.et_key_main);
et_value = (EditText) findViewById(R.id.et_value_main);
tv_desc = (TextView) findViewById(R.id.tv_desc_main);
Button btn_save = (Button) findViewById(R.id.btn_save);
Button btn_first = (Button) findViewById(R.id.btn_first);
Button btn_second = (Button) findViewById(R.id.btn_second);
btn_save.setOnClickListener(this);
btn_first.setOnClickListener(this);
btn_second.setOnClickListener(this);
}
@Override
protected void onStart() {
super.onStart();
tv_desc.setText(mApp.getMapDesc());
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_save) {
if (et_key.getText()==null || et_key.getText().length()<=0) {
Toast.makeText(this, "请输入字段名称", Toast.LENGTH_LONG).show();
return;
} else if (et_value.getText()==null || et_value.getText().length()<=0) {
Toast.makeText(this, "请输入字段值", Toast.LENGTH_LONG).show();
return;
}
mApp.mMap.put(et_key.getText().toString(), et_value.getText().toString());
tv_desc.setText(mApp.getMapDesc());
} else if (v.getId() == R.id.btn_first) {
Intent intent = new Intent(this, FirstActivity.class);
startActivity(intent);
} else if (v.getId() == R.id.btn_second) {
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent);
}
}
}
两个子页面的代码参照主页面代码,就不重复帖了
下面是使用Application完成内存读写的效果图
点此查看Android开发笔记的完整目录