上文的创建的“陋习”app模型层仅包含一个Crime实例,下面将添加一个包含Crime的列表
app的模型层将新增一个CrimeLab对象,该对象是一个数据集中存储池,用来存储Crime对象。当然也应相应的增加一个CrimeListActivity和CrimeListFragment。
1.更新CriminalIntent的模型层
单例与数据集中存储
在本app中,crime数组对象将存储在一个单例里。单例是特殊的Java类,在创建实例时,一个类仅允许创建一个实例
创建单例(CrimeLab.java):
<span style="font-family:Microsoft YaHei;">package com.example.crimialintent; import android.content.Context; /* * 在本app中,crime数组对象将存储在一个单例里。单例是特殊的Java类,在创建实例时,一个类仅允许创建一个实例 * 应用在内存存在多久,单例就能存在多久 * 要创建单例,须创建一个带有似有构造方法及get()方法的类,其中get()方法返回实例。 */ public class CrimeLab { private static CrimeLab sCrimeLab; //s前缀代表静态变量 private Context mAppContext; private CrimeLab(Context appContext){ mAppContext = appContext; } /** * 注意在此方法中,我们并没有直接将Context参数传给构造方法,以为该context可能是activity或者另一个context对象,在应用整个 * 生命周期中我们无法保证CrimeLab需要用到context,context就一直存在,所以,为了保证单例总是有Context可以使用,可以调用 * getApplicationContext()方法。 */ public static CrimeLab get(Context c){ if (sCrimeLab == null) { sCrimeLab = new CrimeLab(c.getApplicationContext()); } return sCrimeLab; } } </span>
创建可容纳Crime对象的ArrayList (CrimeLab.java)
下面我们将Crime对象保存到CrimeLab中去。在CrimeLab的构造方法里,创建一个空的用来保存Crime对象的ArrayList。此外在添加getCrimes()和getCrime(UUID)方法。前者返回数组列表,后者返回带有指定ID的Crime对象。
<span style="font-family:Microsoft YaHei;">package com.example.crimialintent; import java.util.ArrayList; import java.util.UUID; import android.content.Context; /* * 在本app中,crime数组对象将存储在一个单例里。单例是特殊的Java类,在创建实例时,一个类仅允许创建一个实例 * 应用在内存存在多久,单例就能存在多久 * 要创建单例,须创建一个带有似有构造方法及get()方法的类,其中get()方法返回实例。 */ public class CrimeLab { private static CrimeLab sCrimeLab; // s前缀代表静态变量 private Context mAppContext; private ArrayList<Crime> mCrimes; private CrimeLab(Context appContext) { mAppContext = appContext; mCrimes = new ArrayList<Crime>(); //生成100个crime for (int i = 0; i < 100; i++) { Crime c = new Crime(); c.setTitle("第" + i +"个Crime"); c.setSolved(i % 2 == 0); mCrimes.add(c); } } /** * 注意在此方法中,我们并没有直接将Context参数传给构造方法,以为该context可能是activity或者另一个context对象,在应用整个 * 生命周期中我们无法保证CrimeLab需要用到context,context就一直存在,所以,为了保证单例总是有Context可以使用,可以调用 * getApplicationContext()方法。 */ public static CrimeLab get(Context c) { if (sCrimeLab == null) { sCrimeLab = new CrimeLab(c.getApplicationContext()); } return sCrimeLab; } public ArrayList<Crime> getCrimes() { return mCrimes; } public Crime getCrime(UUID id){ for (Crime c : mCrimes){ if(c.getId().equals(id)) return c; } return null; } } </span>
2.创建ListFragment
继承自ListFragment。
CrimeListFragment.java
<span style="font-family:Microsoft YaHei;">package com.example.crimialintent; import java.util.ArrayList; import android.os.Bundle; import android.support.v4.app.ListFragment; public class CrimeListFragment extends ListFragment { //继承自android.support.v4.app private ArrayList<Crime> mCrimes; /* * 该fragment便利方法不仅可以返回托管的activity,且允许fragment处理更多的frgment事务。 */ @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); getActivity().setTitle(R.string.crime_title);//设置操作栏的标题 /** * CrimelistFragment需要先获取存储在CrimeLab中的Crime列表。 */ mCrimes = CrimeLab.get(getActivity()).getCrimes(); } }</span>
3.使用抽象activity托管fragment 下面我们创建一个用于托管CrimeListFragment的CrimeListActivity类,当然首先还是为他创建视图。 对于CrimeListActivity,我们仍可以使用定义在activity_crime.xml文件中的布局。布局文件中并没有指定一个特定的fragment,因此只要有activity托管一个fragment,我们就可以使用该布局文件,为了显示通用性,我们将它重命名为activity_fragment.xml
<span style="font-family:Microsoft YaHei;"><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragmentContainer" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.crimialintent.CrimeActivity" > </FrameLayout> </span>
抽象activity类: 回顾我们前面写的CrimeActivity类,该类代码几近通用,唯一不同的地方就是CrimeFragment类在添加到FragmentManager之前的实例化代码部分:
<span style="font-family:Microsoft YaHei;">fragment = new CrimeFragment();</span>为避免重复性输入,我们创建一个名为SingleFragmentActivity的新类,选择FragmentActivity类作为它的超类,然后勾选abstract选项,让其成为一个抽象类 添加一个通用超类(SingleFragmentActivity):
<span style="font-family:Microsoft YaHei;">package com.example.crimialintent; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; public abstract class SimpleFragmentActivity extends FragmentActivity { protected abstract Fragment createFragment();//>>>>>>>>>>比原CrimeActivity多添加一个抽象方法,我们可以用它实例化新的fragment @Override public void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_fragment); /* * 将Fragment添加到activity中: 1.获取FragmentManager * 2.获取一个Fragment交由FragmentManager管理 */ FragmentManager fm = getSupportFragmentManager();// 获取FragmentManager本身 Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);//通过资源ID向FragmentMananger请求获取Fragment if (fragment == null) { fragment = createFragment(); //>>>>>>>>>>>>>>>>>>>>>>>> //>>>>此处与原来的CrimeActivity(fragment = new CrimeFragment();)代码略有不同 //创建一个新的Fragment事务,加入一个添加操作,然后提交事务 fm.beginTransaction().add(R.id.fragmentContainer, fragment) .commit(); } } } </span>使用抽象类(CrimeListActivity.java):
<span style="font-family:Microsoft YaHei;">package com.example.crimialintent; import android.support.v4.app.Fragment; public class CrimeListActivity extends SimpleFragmentActivity { @Override protected Fragment createFragment() { // TODO Auto-generated method stub return new CrimeListFragment(); // 实现该方法并返回一个新的CrimeListFragment实例 } } </span>CrimeActivity.java:
<span style="font-family:Microsoft YaHei;">package com.example.crimialintent; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; public class CrimeActivity extends FragmentActivity { //继承自FragmentActivity private Fragment createFragment() { // TODO Auto-generated method stub return new CrimeFragment(); } } </span>到真机运行一下
当前还没有内容,但是CrimeListFragment已经被赋予了访问Crime的能力,休息下~ 我们将crime列表通过listview显示在屏幕上