Application和Activity,Service一样是android框架的一个系统组件,
当android程序启动时系统会创建一个application对象,用来存储系统的一些信息。
通常我们是不需要指定一个Application的,这时系统会自动帮我们创建。
打开每一个应用程序的manifest文件,可以看到activity都是包含在application标签之中,如下:
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar" > <activity android:name="com.example.winxinmff.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
android系统会为每个程序运行时创建一个Application类的对象且仅创建一个,所以Application是单例 (singleton)模式的一个类.
且application对象的生命周期是整个程序中最长的,它的生命周期就等于这个程序的生命周期。
因为它是全局的单例的,所以在不同的Activity,Service中获得的对象都是同一个对象。
因此在安卓中我们可以避免使用静态变量来存储长久保存的值,而用Application。
为了更好的利用Application的这一特性,比如我们需要Application来保存一些静态值,需要自定义继承于Application的类,
然后在这个类中定义一个变量来保存。在默认情况下应用系统会自动生成Application 对象,
但是如果我们自定义了Application,那就需要告知系统,实例化的时候,是实例化我们自定义的,而非默认的。
比如我们自定义了一个GlobalApplication类:
package com.example.winxinmff; import android.app.Application; import android.database.sqlite.SQLiteDatabase; import android.util.Log; public class GlobalApplication extends Application { // 公共的 写在这里 private String tag = "application"; private DatabaseHelper db_helper; public void onCreate() { Log.i(tag, "onCreate执行了"); // 此3行代码用于创建表结构,以及初始化数据 MyDatabaseOpenHelper helper = new MyDatabaseOpenHelper(this); SQLiteDatabase db = helper.getWritableDatabase(); db.close(); // db_helper = new DatabaseHelper(this); super.onCreate(); } public void onTerminate() { Log.i(tag, "onTerminate 执行了,程序真的over"); super.onTerminate(); } public void onLowMemory() { Log.i(tag, "onLowMemory 执行了,警告,有想杀你的冲动,但没杀..."); super.onLowMemory(); } public void onTrimMemory(int level) { db_helper.close(); db_helper = null; Log.i(tag, "onTerminate 执行了,基本上会在activit休眠的时候执行"); super.onTrimMemory(level); } public DatabaseHelper getDb_helper() { if (db_helper == null) { db_helper = new DatabaseHelper(this); } return db_helper; } }
为了让系统实例化的时候找到,我们必须在manifest(清单文件)中修改application标签属性:
<application android:name="com.example.winxinmff.GlobalApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar" > <activity android:name="com.example.winxinmff.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
关键的是这句:
通常Application全局对象是通过Context或者Activity的getApplicationContext()方法
获得的比如我们在应用程序中想要获得我们刚刚定义的GlobalApplication 对象,就需要在activity中这样做:
app = (GlobalApplication) this.getApplication();
如果有Context对象,还可以:app = (GlobalApplication)mContext.getApplicationContext();
但是很多时候我们的代码可能在activity之外,且没有context对象的引用,但是又需要获得GlobalApplication对象,
原始的做法可能是想办法将activity或者context传递到需要调用的地方,但是这样代码耦合度太高,可读性差。我们有更优雅的做法。
我们谈到Application对象是全局的,单例的,既然是单例应该有一个类方法能让我们获得这个单例对象才是,但Application本身没有,我们只能在自定义的时候想办法。
Application是系统的一个组件,也就有自己的生命周期函数,
让人感到意外的是他的生命周期函数中居然也有onCreate(),onCreate是被自动调用的,我们可以利用这点来获得这个Application对象。
在GlobalApplication中加入如下几行代码:
数据库助手的get方法
这样我们就能在app工程的任何地方通过GlobalApplication.getDb_helper()来获得Application全局对象。比如我定义了一个工具类,在工具内中我们需要使用
Context的getExternalFilesDir()方法。但是这个工具类没有直接的办法获取到context,于是我们可以:
package com.example.winxinmff; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.SimpleAdapter; import android.widget.Toast; import com.example.entity.Message; import com.example.winxinmffSQL.R; import com.j256.ormlite.dao.Dao; public class MainActivity extends Activity { private SimpleAdapter sa; // 是android中一个列表适配器 主要用于做一些简单的列表适配 private ListView lv; private List<Message> messageList = new ArrayList<Message>(); private List<Map<String, Object>> messageList2 = new ArrayList<Map<String, Object>>(); private List<Message> messageList3 ; // 用于ORMLite // 看名字就是databasehelper,数据库助手的意思,这本身就是一个类。 // 包含了数据库连接,关闭,如果有拓展的话 可能包含基本的数据库JDBC操作方法也就是简化增删改查的一些方法。 // private DatabaseHelper db_helper; // 其他 private GlobalApplication app = null; // 自己建的类 // 没有前生 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.weixin); app = (GlobalApplication) this.getApplication(); Log.i("ok", "onCreate 执行了"); lv = (ListView) findViewById(R.id.listView1); sa = new SimpleAdapter(this, messageList2, // data 不仅仅是数据,而是一个与界面耦合的数据混合体 R.layout.listview_item_layout, new String[] { "tou", "userName", "lasMessage", "datetime" }, // from 从哪来 new int[] { R.id.imageView1, R.id.tv_userName, R.id.tv_lasMessage, R.id.tv_datetime }// to 到哪去 ); lv.setAdapter(sa); lv.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Map<String, Object> item = messageList2.get(position); item.put("userName", "阿凡达" + position); sa.notifyDataSetChanged(); // Toast.makeText(MainActivity.this, (String)item.get("userName"), Toast.LENGTH_SHORT).show(); } }); // 简单理解为VC绑在一起 } // UI呈现在眼前 protected void onResume() { Log.i("ok", "onResume,界面出现了,app"+app); // 使用 ORMLite // db_helper = new DatabaseHelper(this); Dao<Message, Integer> message_dao = app.getDb_helper().getMessageDao(); try { messageList3 = message_dao.queryForAll(); // Log.i("ormlite", "记录条数:"+messageList3.size()); String t = "记录条数:" + messageList3.size(); Toast.makeText(this, t, Toast.LENGTH_LONG).show(); } catch (SQLException e) { String t = "记出错:" + e.getMessage(); Toast.makeText(this, t, Toast.LENGTH_LONG).show(); } // 模拟读取数据库或者互联网 for (int i = 0; i < messageList3.size(); i++) { Message p = new Message(); p.setTou1("xxx"); p.setUserName("不对外开放 高内聚 "); p.setLastMessage("匿名内部类也就是没有名字的内部类匿名内部类也就是没有名字的内部类"); p.setDatetime("11.11"); messageList.add(p);// 上周 // 定义一个界面与数据的混合体,一个item代表一行记录 Map<String, Object> item = new HashMap<String, Object>(); // 一行记录,包含多个控件 item.put("tou", R.drawable.a); item.put("userName", messageList3.get(i).getUserName() + i); item.put("lasMessage", messageList3.get(i).getLastMessage()); item.put("datetime", messageList3.get(i).getDatetime()); messageList2.add(item); } super.onResume(); } // UI完全显示在眼前,完全被另一个进程覆盖 protected void onPause() { Log.i("ok", "onPause,被抛弃了"); app.getDb_helper().close();// ??到底要不要? super.onPause(); } }
现在就可以多次使用数据库助手了