在做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。。。如果你覺得還不錯請收藏。以後的文章會寫到其他設計模式。