上一次我写了一个Fragment的简单使用,这次我来实现这个:
首先想想上次写的东西 crime类 crimeFragmnet类 crimeActivity类
如上图的的前三个类。和上次一样这次我们来建CrimeLab类 crimeListFragement类和crimeListActivity类。
上次,我们为fragment加入xml布局文件,我们在重写onCreateView的方法中使用inflater把xml文件填充到我们的fragment;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View v=inflater.inflate(R.layout.fragment,container,false); 现在来看看这次我们的fragmnet类的代码
1 package com.example.leiyunjie.crime; 2 3 import android.os.Bundle; 4 import android.support.v4.app.ListFragment; 5 import android.util.Log; 6 import android.view.View; 7 import android.widget.ArrayAdapter; 8 import android.widget.ListView; 9 10 import java.util.ArrayList; 11 12 /** 13 * Created by leiyunjie on 2016/4/21. 14 */ 15 public class CrimeListFragment extends ListFragment { 16 17 private ArrayList<crime> mCrimes; 18 private static final String TGA="CrimeListFragment"; 19 @Override 20 public void onCreate(Bundle savedInstanceState){ 21 super.onCreate(savedInstanceState); 22 getActivity().setTitle("Crimes"); 23 mCrimes=CrimeLab.get(getActivity()).getmCrimes(); 24 25 ArrayAdapter<crime> adapter= 26 new ArrayAdapter<crime>(getActivity(), 27 android.R.layout.simple_expandable_list_item_1, 28 mCrimes); 29 setListAdapter(adapter); 30 31 } 32 @Override 33 public void onListItemClick(ListView l, View v, int position, long id){ 34 crime c=(crime)(getListAdapter()).getItem(position); 35 Log.d(TGA,c.getmTitle()+"was clicked"); 36 } 37 }
crimelistFragment
这次我们的public class CrimeListFragment extends ListFragment 也就是这个crimelistfragment继承ListFragment,而ListFragment 类默认实现方法已生成了一个全屏 ListView 布局,我们也就可以不用自己布局了。现在我们要做的就是把要显示的crimelab对象放进这个listview布局。
现在来看看crimelab的代码
1 package com.example.leiyunjie.crime; 2 3 import android.content.Context; 4 5 import java.util.ArrayList; 6 import java.util.UUID; 7 8 /** 9 * Created by leiyunjie on 2016/4/21. 10 */ 11 12 //单例 13 public class CrimeLab { 14 private ArrayList<crime> mCrimes; 15 16 private static CrimeLab sCrimeLaab; 17 private Context mAppContext; 18 19 //随机产生100个实例 20 private CrimeLab(Context appContext){ 21 mAppContext=appContext; 22 mCrimes=new ArrayList<crime>(); 23 for(int i=0;i<100;i++){ 24 crime c=new crime(); 25 c.setmTitle("crime #"+i); 26 c.setmSolved(i%2==00); 27 mCrimes.add(c); 28 } 29 30 31 } 32 public static CrimeLab get(Context c){ 33 if(sCrimeLaab==null){ 34 sCrimeLaab=new CrimeLab(c.getApplicationContext()); 35 } 36 return sCrimeLaab; 37 } 38 39 public ArrayList<crime> getmCrimes(){ 40 41 return mCrimes; 42 } 43 44 public crime getCrime(UUID id){ 45 for(crime c:mCrimes){ 46 if(c.getmID().equals(id)) 47 return c; 48 } 49 return null; 50 } 51 52 53 54 }
crimelab
我们将crime数组对象存储在一个单例里。单例是特殊的java类,在创建实例时,一个类仅允许创建一个实例。应用能够在内存里存在多久, 单例就能存在多久, 因此将对象列表保存在单例里可保持crime数据的一直存在,不管activity、fragment及它们的生命周期发生什么变化。要创建单例,需创建一个带有私有构造方法及 get() 方法的类,其中 get() 方法返回实例。如实例已存在, get() 方法则直接返回它;如实例还未存在, get() 方法会调用构造方法来创建它。
public static CrimeLab get(Context c){ if(sCrimeLaab==null){ sCrimeLaab=new CrimeLab(c.getApplicationContext()); } return sCrimeLaab;}
为了看看效果我产生100个随机对象来填充arraylist:
private CrimeLab(Context appContext){ mAppContext=appContext; mCrimes=new ArrayList<crime>(); for(int i=0;i<100;i++){ crime c=new crime(); c.setmTitle("crime #"+i); c.setmSolved(i%2==00); mCrimes.add(c); }
现在我们有了一个有着100个随机产生的crime对象的arraylist,接下来把他放到fragment中先获得该arrylist
private ArrayList<crime> mCrimes;
mCrimes=CrimeLab.get(getActivity()).getmCrimes();
然后该使用adapter来工作了: ArrayAdapter<crime> adapter= new ArrayAdapter<crime>(getActivity(), android.R.layout.simple_expandable_list_item_1, mCrimes); setListAdapter(adapter); }顺便说说adapter: adapter的继承关系:
adapter和listview的对话
创建ArryAdapter时必须指定三个参数:Context,textViewResourceId,数组或list。对应上面的getActivity(), android.R.layout.simple_expandable_list_item_1, mCrimes。
就是把数组或list中的东西放到android.R.layout.simple_expandable_list_item_1代表的一个textview中,该textview将作为ArryAdapter的列表组件。
放好后我们就把Adapter反到ListView中就ok了,setListAdapter(adapter); 前面省略了默认的全屏 ListView 。
fragment算是写好了,现在要写一个activity来托管这个fragmnet了
看看代码
1 package com.example.leiyunjie.crime; 2 3 import android.support.v4.app.Fragment; 4 5 /** 6 * Created by leiyunjie on 2016/4/21. 7 */ 8 public class CrimeListActivity extends SingleFragmentActivity { 9 @Override 10 protected Fragment createFragment(){ 11 return new CrimeListFragment(); 12 } 13 }
crimelistactivity
是的,我们完全可以和上次写的activity代码一样,只不过要在一下代码段
if(fragment==null){
fragment=XXXXXX;
fm.beginTransaction()
.add(R.id.fragment,fragment)
.commit();
}
}
对就是 fragment=XXXXXX;这里不一样,如果我们要写很多不同的activity去托管fragment时,大部分代码就是在重复,这时我们可以考虑建立一个抽象类去减少吃饭代码
我们建立一个singlefragmentactivity类
1 package com.example.leiyunjie.crime; 2 3 import android.os.Bundle; 4 import android.support.v4.app.Fragment; 5 import android.support.v4.app.FragmentActivity; 6 import android.support.v4.app.FragmentManager; 7 8 /** 9 * Created by leiyunjie on 2016/4/21. 10 */ 11 public abstract class SingleFragmentActivity extends FragmentActivity { 12 protected abstract Fragment createFragment(); 13 @Override 14 public void onCreate(Bundle saveInstanceState){ 15 super.onCreate(saveInstanceState); 16 setContentView(R.layout.activity_fragment); 17 FragmentManager fm=getSupportFragmentManager(); 18 Fragment fragment=fm.findFragmentById(R.id.fragment); 19 if(fragment==null){ 20 fragment=createFragment(); 21 fm.beginTransaction() 22 .add(R.id.fragment,fragment) 23 .commit(); 24 } 25 } 26 }
SingleFragmentActivity
是的,在里面我使用了fragment=createFragment();
然后我们再新建activity时只要继承该抽象类,然后去实现该方法就ok了;
比如我们回到上一篇的文章,把其中的activity.java文件进行修改
package com.example.leiyunjie.crime; import android.support.v4.app.Fragment; public class crimeActivity extends SingleFragmentActivity { @Override protected Fragment createFragment(){ return new crimeFragmnet(); } }
现在的代码清爽多了不是。
总结一下,这部分还是很简单的,就比上一篇文章多了arrayliat和arryadapter,以及建了个抽象类。注意这次我们继承的是listfragment类,所以不需要为fragment指定布局文件,其次activity的布局文我们还是使用的上次的布局文件,也就是在SingleFragmentActivity中的
public void onCreate(Bundle saveInstanceState){ super.onCreate(saveInstanceState); setContentView(R.layout.activity_fragment);......这也大大将少了代码量,以后的学习中要尽量养成这种简约的习惯,养成良好的代码习惯