上文的创建的“陋习”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>
到真机运行一下