在做android 通讯录的历史记录,因为需求的繁琐,且变态,又整天被老板催着赶项目。本人又是菜鸟,所以项目代码写的哪个繁琐啊,垃圾。
先吐槽下,开始正题。
复习下观察者模式
对象:观察者,被观察者。
我们可以理解为被观察者就是我门需要的数据源,观察者就是我们数据源更改变化之后,我们需要变化的界面啊,类啊。什么东东的。
想想android的adapter中的notifyDataSetChanged。它底层实现必须是用了观察者模式。
直接上代码
被观察者要继承java中的Observable。实现了Observable 就可以使用add方法添加观察者。romve 方式溢出观察者。
对了被观察者通知观察者数据源发生变化是通过setChanged(); notifyObservers();来通知的。其实和android中的 adapter.notifyDataSetChanged();一样的。
下面是被观察者的代码
package bsn.report.person; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Observable; import android.app.Activity; import android.content.AsyncQueryHandler; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.provider.Contacts; /** *通讯录历史记录 的数据源 *我把他当做被观察者 * @author Administrator * */ public class ContactsHistoryObserver extends Observable { private ListQueryHandler mQueryHandler; private PhoneContact phoneContact; private MyApplication application; private int sdkVersion = 4; private static List<PhoneContact>phoneContacts= new ArrayList<PhoneContact>(); private String mColumnName = null,mColumnNumber=null,mColumnType=null,mColumnDate=null; private ContactsHistoryObserver historyObserver; public static boolean FINDBL=false; ContactsHistoryObserver(Context context){ historyObserver=new ContactsHistoryObserver(); application=(MyApplication) context.getApplicationContext(); mQueryHandler=new ListQueryHandler(context.getContentResolver()); queryList(mQueryHandler); } ContactsHistoryObserver(){ } public void setData(boolean findbl){ FINDBL=findbl; } public void setHistoryContact( List<PhoneContact>phoneContacts){ this.phoneContacts=phoneContacts; setChanged(); notifyObservers(); } public void queryList(AsyncQueryHandler async) { if (async != null) { try { sdkVersion = Integer.parseInt(android.os.Build.VERSION.SDK.trim()); } catch (Exception e) { sdkVersion = 3; } Uri personUri = null; if(sdkVersion > 4){//2.x,sdk版本 personUri = Uri.parse("content://call_log/calls"); mColumnName = "name"; mColumnNumber="number"; mColumnType="type"; mColumnDate="date"; }else{//1.6以下SDK personUri = Contacts.People.CONTENT_URI; mColumnName = Contacts.People.NAME; } //开始异步查询 async.startQuery(0, null, personUri, null, null, null, null); } } public static List<PhoneContact> getAllData(){ return phoneContacts; } class ListQueryHandler extends AsyncQueryHandler { public ListQueryHandler(ContentResolver cr) { super(cr); } /** * 异步查询结束时 */ public void onQueryComplete(int token, Object cookie, Cursor cursor) { String name = null, number = null; int type=0; if (cursor != null) { try { int nameIndex = cursor.getColumnIndex(mColumnName); int numberIndex = cursor.getColumnIndex(mColumnNumber); int typeIndex = cursor.getColumnIndex(mColumnType); int dateIndex = cursor.getColumnIndex(mColumnDate); cursor.moveToFirst(); while (cursor.moveToNext()) { phoneContact=new PhoneContact(); number = cursor.getString(numberIndex); name = cursor.getString(nameIndex); type = cursor.getInt(typeIndex); phoneContact.setName(name); phoneContact.setPhone_type(type); phoneContact.setPhone_time(Long.parseLong(cursor.getString(dateIndex))); phoneContacts.add(phoneContact); } setHistoryContact(phoneContacts); // this.ContactsHistoryObserver.addObserver(allConacts); cursor.close(); //在这里为所有通话记录 和未接电话加入监听。 AllConacts allConacts=new AllConacts(); MissContacts missContacts=new MissContacts(); historyObserver.addObserver(allConacts); historyObserver.addObserver(missContacts); historyObserver.setData(true); historyObserver.setHistoryContact(phoneContacts); Collections.sort(phoneContacts, new Comparator<PhoneContact>() { @Override public int compare(PhoneContact object1, PhoneContact object2) { int compareName=String.valueOf(object2.getPhone_time()).compareTo(object1.getPhone_time()+""); return compareName; } }); } catch (Exception e) { // TODO: handle exception } } } } }
tab代码 。这里主要是记下其中的模式,没完善tab
package bsn.report.person; import android.app.TabActivity; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.TabHost; import android.widget.RadioGroup.OnCheckedChangeListener; public class WeiCall_CallTabUI extends TabActivity implements OnCheckedChangeListener{ private RadioGroup mainTab; private RadioButton rbPhoneContact; private RadioButton rbFriend; private TabHost mTabHost; // 内容Intent private Intent mChatIntent; private Intent mContactsIntent; private MyApplication application; private final static String TAB_TAG_CURRENT_CHAT = "tab_tag_chat"; private final static String TAB_TAG_CONTACTS = "tab_tag_contacts"; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.weicall_call_menu); mainTab = (RadioGroup) findViewById(R.id.main_tab); mainTab.setOnCheckedChangeListener(this); application=(MyApplication) getApplication(); rbFriend = (RadioButton) findViewById(R.id.radio_button1); rbPhoneContact = (RadioButton) findViewById(R.id.radio_button2); prepareIntent(); setupIntent(); } /** * 准备tab的内容Intent */ private void prepareIntent() { mChatIntent = new Intent(this, AllConacts.class); mContactsIntent = new Intent(this, MissContacts.class); } /** * */ private void setupIntent() { this.mTabHost = getTabHost(); TabHost localTabHost = this.mTabHost; localTabHost.addTab(buildTabSpec(TAB_TAG_CURRENT_CHAT, "所有电话", R.drawable.icon, mChatIntent)); localTabHost.addTab(buildTabSpec(TAB_TAG_CONTACTS, "未接电话", R.drawable.icon, mContactsIntent)); } /** * 构建TabHost的Tab页 * * @param tag * 标记 * @param resLabel * 标签 * @param resIcon * 图标 * @param content * 该tab展示的内容 * @return 一个tab */ private TabHost.TabSpec buildTabSpec(String tag, String lable, int resIcon, final Intent content) { return this.mTabHost.newTabSpec(tag) .setIndicator(lable, getResources().getDrawable(resIcon)) .setContent(content); } @Override public void onCheckedChanged(RadioGroup group, int checkedId) { switch (checkedId) { case R.id.radio_button1: rbFriend.setTextColor(Color.WHITE); rbPhoneContact.setTextColor(Color.GRAY); this.mTabHost.setCurrentTabByTag(TAB_TAG_CURRENT_CHAT); break; case R.id.radio_button2: rbFriend.setTextColor(Color.GRAY); rbPhoneContact.setTextColor(Color.WHITE); this.mTabHost.setCurrentTabByTag(TAB_TAG_CONTACTS); break; } } }
接下是观察者之一的所有拨打电话记录 这里重点看其中的update方法
package bsn.report.person; import java.util.ArrayList; import java.util.List; import java.util.Observable; import java.util.Observer; import android.app.Activity; import android.app.ProgressDialog; import android.os.Bundle; import android.widget.Adapter; /** * 拨打联系人历史记录 * 观察者 * @author Administrator * */ public class AllConacts extends Activity implements Observer{ private List<PhoneContact>phoneContacts= new ArrayList<PhoneContact>(); private ProgressDialog dialog; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.allcontact); dialog=new ProgressDialog(this); ContactsHistoryObserver observer=new ContactsHistoryObserver(this); } @Override public void update(Observable observable, Object data) { ContactsHistoryObserver observer=(ContactsHistoryObserver) observable; System.out.println( " observer.FINDBL;"+observer.FINDBL); if (observer.FINDBL==false) { if (dialog!=null) { dialog.show(); } }else{ //请注意这里就得到了我们应该得到的数据。。。直接在adapter中显示出来就行。 ContactsHistoryObserver.getAllData(); dialog.cancel(); } } }
观察者2:未接电话
package bsn.report.person; import java.util.Observable; import java.util.Observer; import android.app.Activity; import android.os.Bundle; /** * 未接电话的类 * 观察者之1 * 这里可以仿照AllConacts * 只是一个测试所以没有写出来 * @author Administrator * */ public class MissContacts extends Activity implements Observer{ @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.misscontact); } @Override public void update(Observable arg0, Object arg1) { // TODO Auto-generated method stub } }
最好把domain的类也放进来吧
package bsn.report.person; public class PhoneContact { private String name; private long id; private long phone_time; private int phone_type; / private String lookupKey; public long getPhone_time() { return phone_time; } public void setPhone_time(long phone_time) { this.phone_time = phone_time; } public int getPhone_type() { return phone_type; } public void setPhone_type(int phone_type) { this.phone_type = phone_type; } public String getLookupKey() { return lookupKey; } public void setLookupKey(String lookupKey) { this.lookupKey = lookupKey; } public long getId() { return id; } public void setId(long id) { this.id = id; } //增加一个比较两个对象的整数值 private int temp=2; public int getTemp() { return temp; } public void setTemp(int temp) { this.temp = temp; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; PhoneContact other = (PhoneContact) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
package bsn.report.person; public class PhoneContact { private String name; private long id; private long phone_time; private int phone_type; / private String lookupKey; public long getPhone_time() { return phone_time; } public void setPhone_time(long phone_time) { this.phone_time = phone_time; } public int getPhone_type() { return phone_type; } public void setPhone_type(int phone_type) { this.phone_type = phone_type; } public String getLookupKey() { return lookupKey; } public void setLookupKey(String lookupKey) { this.lookupKey = lookupKey; } public long getId() { return id; } public void setId(long id) { this.id = id; } //增加一个比较两个对象的整数值 private int temp=2; public int getTemp() { return temp; } public void setTemp(int temp) { this.temp = temp; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; PhoneContact other = (PhoneContact) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
好了到这里观察者模式在android中的应用写完了。大神勿喷。
写这些文章的目的是给自己学习记录,如果能对你起到帮助那是我的荣幸,如果你觉得文章写的不正确,请回复。。。。
如果文章看着让你不爽了请直接alt+F4。。。如果你觉得还不错请收藏。以后的文章会写到其他设计模式。