1、我們有時會遇到如下問題。當有兩個或多個UI類展示界面大體相同,但需要展示不同的內容,並且這些類之間都要相互交換或者刷新數據。繁瑣的做法是爲每一個UI類都建立新的佈局,這樣便出現了很多冗餘佈局,當它們之間需要交換業務時,直接把這些類的引用到處傳遞也是很頭疼的事情,這時可用抽象了類來解決這個問題。當然,Fragement完全可以實現這樣的功能,但也有它所不能施展的地方。
例:
有三個頁面展示的類,爲FirstUI、SecondUI、ThirdUI,它們所展示的頁面分爲三個部分,分別是標題欄,內容展示欄,底部狀態欄,這時可將這三個部分抽取到抽象類中,在實現類裏實現中間類型的動態加載以及對上下狀態欄的數據刷新(這裏沒提取公共View,而是放到了各個管理器裏了)。
代碼如下:
抽象父類:
public abstract class BaseUI implements OnclicListener{
private Context context;
public BaseUI(Context context){
this.context = context;
}
//獲取展示界面
public abstract View getChild();
//標識是哪一個界面
public abstract int getID();
@Override
public void onClick(View v) {
//並不是所有的界面都需要有點擊事件,需要用到時,在複寫這個方法
}
}
然後FirstUI類如下,其餘不在鰲訴:
public class FirstUI extends BaseUI {
private Context context;
private TextView view;
public FirstUI(Context context) {
super(context);
this.context = context;
init();
}
public void init(){
view = new TextView(context);
LayoutParams params = view.getLayoutParams();
params = new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.MATCH_PARENT);
view.setLayoutParams(params);
view.setBackgroundColor(color.green);
view.setText("This is a first page!");
}
public View getChild() {
return view;
}
@Override
public int getID() {
// TODO Auto-generated method stub
return Constant.VIEW_FIRST; //建議將這個ID類型放在常量類中,便於統一管理
}
}
而在進行用戶界面切換時,不需要給出具體實現類,可以採用字節碼,而字節碼
也不是任何類型都可以傳遞進來的,應該只能是BaseUI類的子類。
public void changeUI(Class<? extends BaseUI> targetClazz) {
String key = targetClazz.getSimpleName();//獲取類名
if (viewAche.containsKey(key)) {
targetUI = viewAche.get(key);
} else {
try {
//得到他的構造器
Constructor<? extends BaseUI> constructor = targetClazz
.getConstructor(Context.class);
targetUI = constructor.newInstance(getContext());
viewAche.put(key, targetUI);
} catch (Exception e) {
throw new RuntimeException("BaseUI Constructor Error!");
}
}
}
2、當有多個容器各自管理着自己的任務,當某個容器內容變化後,與之相聯繫的容器也應當變化,傳統的方式是在需要變化的容器內部進行更改,這樣做之後會增大它們之間的耦合度,此時可以採用觀察者模式進行解耦,當數據需要更改時,通知觀察者改變數據。
具體做法,可以採用Java類庫裏的Observable類,也可以自己寫一個這樣的類(不建議哦!你對自己的編碼能力是否有信心),繼承它!
//繼承已有工具類Observable
public class MiddleManager extends Observable {
private MiddleManager() {
}
}
private void change() {
// 觀察者模式,改變監聽狀態,通知觀察者數據改變了
this.setChanged();
//otherClass已註冊的類的ID
this.notifyObservers(otherClass.getID());
}
添加觀察的對象。
private void init() {
TitleManager manager = TitleManager.getInstance();
manager.init(this);
manager.showLoginTitle();
BottomManager bottom=BottomManager.getInstrance();
bottom.init(this);
bottom.showCommonBottom();
MiddleManager middle = MiddleManager.getInstance();
middle.setMiddle(ii_middle);
middle.changeUI(HallViewPager.class);
//觀察者模式,添加觀察者
middle.addObserver(manager);
middle.addObserver(bottom);
}
被觀察者實現Observer接口,更新數據
//實現Obserever接口,實現Observer的方法
public class TitleManager implements Observer{
@Override
public void update(Observable observable, Object data) {
//乾點壞事,別人都不知道
}
}
3、如果一個組件想要得到當前上下文,可以組件自身來獲取。如下:
middle是一個Linearlayout,這樣做可以防止當前上下文到處傳遞引用,避免造成內存泄漏。
public class ClassTemp{
//同過組件自身獲得當前上下文
public Context getContext() {
return middle.getContext();
}
//通過view自己的父親那裏得到移除的方法,把自己幹掉,就是自殺
public void init(LinearLayout view){
ViewGroup parent=(ViewGroup)view.getParent();
parent.removeView(view);
}
}
4、當使用LinearLayout佈局時,發現(圖.1)中的情況,這說明佈局文件填充全部寬度沒有起作用,導致的原因是root爲空的時候,它不會設置LayoutParams。做法是自己去填充一下。代碼如下:
showInMiddle = (LinearLayout) View.inflate(context, R.layout.il_hall1,
null);
if (showInMiddle.getLayoutParams() == null) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
showInMiddle.setLayoutParams(params);
}
圖 1 手機界面未填充滿效果圖(盜圖)
5、動態更改ListView的孩子,不影響已經加載的item。
首先爲每一個item設置一個tag:
holder.iv_news.setTag(position);
得到要更新的組件:
TextView view = listview.findViewWithTag(position);
進行更新即可;
6、當在GridView中顯示很多個相同的圖片,而只是裏面的文字不同,比如彩票的號碼,他們的背景圖片都一樣,只是它們顯示的文字不一樣,那麼我們可以用TextView來填充,不用將每張圖片都畫一遍,那樣做的代價是很
大的,例子如下:
@Override
public int getCount() {
// TODO Auto-generated method stub
return endNum; //你要顯示的球的個數
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
**TextView view = new TextView(context);
DecimalFormat decimalFormat = new DecimalFormat("00");
view.setText(decimalFormat.format(position + 1));
view.setBackgroundResource(R.drawable.id_defalut_ball);
view.setTextSize(16);
view.setGravity(Gravity.CENTER);**
return view ;
}
7、當有多個TextView要顯示,並且顏色還不一樣,可以用fromHtml進行轉化,就不需要寫那麼的TextView了,例如:
定義數據:
<![CDATA[注數:  <font color="#ff0000">NUM</font>  注  金額:  <font color="#ff0000">MONEY</font>元]]>
String noticeInfo = context.getResources().getString(
R.string.is_shopping_list_notice);
noticeInfo = StringUtils.replaceEach(noticeInfo, new String[] { "NUM",
"MONEY" }, new String[] { lotterynumber.toString(),
lotteryvalue.toString() });
// Html.fromHtml(notice):將notice裏面的內容轉換
notice.setText(Html.fromHtml(noticeInfo));
8、當在做一個手機端程序,需要上傳數據到網絡,但又苦於用戶可能沒有網絡,此時可以採用離線上傳的做法。
首先,在本地數據庫保存數據,用戶每上傳成功一條,你都要記錄到本地數據庫,已實現數據同步,但又要避免不斷髮送和接受重複數據,導致用戶流量增加。此時,可以在設計數據庫時設計兩個表,一個是本地緩存表,一個是待上傳的數據表,每上傳成功一個就刪去待上傳數據表中的數據。這種做法如同凍結資金錶。
9、項目使用的配置文件(bean.properties)必須跟隨在src目錄下。
10、圖片中紅色框裏的東西代表,當把apk文件變爲jar包的時候,讓程序去自動管理資源文件的ID,不勾選會出現很蛋疼的問題(資源文件命名規則很重要)。
圖2 eclispse創建工程界面
11、Android中點擊圖標不顯示activity界面的辦法,在清單文件裏設置系統主題不顯示界面(鎖屏軟件用得上哦)。
android:theme="@android:style/Theme.NoDisplay" />
12、建立殺不死的服務。這個有點狠,違背道德啊!僅供學習測試參考,開發人員慎用,出現後果自負,與本小編無關。
(1)進程守護
創建連個相同的服務,在
@Override
public void onDestroy() {}
方法裏對另外一個服務啓動,反過來相同,便可以達到目的
(2)廣播接收者
用廣播監聽各種廣播事件,當這個時間發生後,便會啓動這個服務;
13、Android引用資源位圖更改大小方法 。
//以Drawable取得資源裏的圖片
Drawable drawable = this.getResources().getDrawable(R.drawable.white);
//設置位圖的大小與位置
drawable.setBounds(0, 0, pointSize, pointSize);
//創建一個內容爲空的位圖對象,這個位圖對象在內存裏是空的,並沒有什麼內容
Bitmap bitmap = Bitmap.createBitmap(pointSize, pointSize, Config.ARGB_8888);
//創建一個畫布,將上面創建的位圖畫在這個畫布上,此時這個畫布也是空的,並沒有什麼東西
Canvas can = new Canvas(bitmap);
//調用Drawable自身的draw方法,將它自己畫在剛纔創建的額畫布上
drawable.draw(can);
//最候,便可以得到自己想要多大並且可以在人員位置繪畫的drawable資源裏的圖片
canvas.draw(bitmap,x,y,paint);
14、如何選擇最佳存儲選項。
(1)如果數據可以使用鍵/值對來標識,那麼久使用SharedPreferences對象。
(2)如果需要存儲臨時數據,勇士內部存儲器是一個很好的選擇。
(3)有時需要和其他用戶共享應用 程序數據,這時候可以將文件存儲在設備上的SD卡上。
15、讓文本框獲得焦點,但不顯示輸入法面板。
<activity
android:name="com.example.autoui.MainActivity"
android:label="@string/app_name"
android:windowSoftInputMode="stateHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
16、使用Collections.sort(*,*)實現對數據的亂序處理。參數“T”代表你的數據類型,需要傳入List對象。
Collections.sort(new ArrayList<T>(), new Comparator<T>() {
@Override
public int compare(T lhs, T rhs) {
//因爲你永遠無法知道它返回的是1還是-1,所以在比較時也無法
//知道誰大誰小,達到亂序的可能;
return Math.random() > 0.5 ? 1 : -1;
}
});
17、從圖庫(gallery)獲取一張圖片。
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
//獲取image的uri
Uri imageFileUri = intent.getData();
//bmpFactoryOptions 圖片的Options,直接加載到內存可能會OOM哦
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().
openInputStream(imageFileUri), null, bmpFactoryOptions);
18、獲取圖片文件獲取Exif信息。
//從文件獲取exif信息
ExifInterfaceei = new ExifInterface(imageFilePath);
String imageDescription = ei.getAttribute("ImageDescription");
if (imageDescription != null)
{
Log.v("EXIF", imageDescription);
}
//把exif信息寫到文件:
ExifInterfaceei = new ExifInterface(imageFilePath);
ei.setAttribute("ImageDescription","Something New");
19、獲取手機網卡mac地址,記得加權限。
//權限
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
private String getLocalMacAddress() {
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifi.getConnectionInfo();
return info.getMacAddress();
}
本人初出茅廬,文中難免有錯誤之處,還望指正,謝謝!