1.設置TextView的文本顏色
1
2
3
|
TextView
tv; ... tv.setTextColor(R.color.white); |
其實這樣設置的顏色是 R.color.white的資源ID值所代表的顏色值,而不是資源color下的white顏色值:正確的做法如下:
1
|
tv.setTextColor(getResources().getColor(R.color.white)); |
這個出錯的概率滿高的,就是因爲二者都是int類,導致編譯器不報錯。
2.讀取Cursor中的值
1
2
3
4
5
6
7
|
Uri
uri; Cursor
cursor = contentResolver.query(uri, null , null , null , null ); if (cursor
!= null ){ String
name = cursor.getString(1); // curosr.close(); cursor
= null ; } |
上面語句中的,執行到cursor.getString(1)部分就會報異常,異常是: Caused by: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 4
編譯沒有問題,只有在運行的時候纔會發現。
正確的做法是:
1
2
3
4
5
6
7
8
9
|
Uri
uri; Cursor
cursor = contentResolver.query(uri, null , null , null , null ); if (cursor
!= null ){ if (cursor.moveToFirst()){ String
name = cursor.getString(1); // } curosr.close(); cursor
= null ; } |
或者:
1
2
3
4
5
6
7
8
9
|
Uri
uri; Cursor
cursor = contentResolver.query(uri, null , null , null , null ); if (cursor
!= null ){ while (cursor.moveToNext()){ String
name = cursor.getString(1); // } curosr.close(); cursor
= null ; } |
3.不要使用標有Deprecated的函數或者類,比如不要使用android.telephony.gsm.SmsMessage,而應該用android.telephony.SmsMessage,這樣避免採用不同的3G協議時不會出現問題。
4.SQLite中的查詢條件,比如一個叫name的字段,其字段類型爲TEXT,如果我們要判斷其name不等某個值(如zhangsan),寫出如下的語句
1
|
name
<> 'zhangsan' |
但是,這樣寫的語句,如果碰到name值爲空的時候,就有問題,即name爲空時 以上的布爾值爲false,而不是true.
原因很可能,SQLite中的判斷函數採用類似寫法:
1
2
3
4
|
boolean
judge(String self, String conditions){ if ( null ==
self) return false ; return self.equalsIgnoreCase(conditions); } |
其中 self爲數據庫中name的值,而conditions爲上面示例中的 zhangsan。
所以,以上查詢條件的正確寫法是:
1
|
name
<> 'zhangsan' or
name is null |
除非你也想過濾掉name 爲空的記錄。
5.如下所示,想要在按鈕顯示"刪 除"(沒錯刪除中間有個空格),以下的字符串資源是錯誤的:
1
|
<string
name= "button_delete_text" >刪
除</string> |
這樣的出來,最終看不到中間的空格,應該是Android SDK編譯的時候,會自動過濾掉String中的空格部分,所以應該採用以下的方式:
1
|
<string
name= "button_delete_text" >刪\u0020除</string> |
類似地,其他的特殊符號都可以用\u00XX來轉義,如 ' ---- \u0027, < ----- \u003C, > ---- \u003E 。
注意這裏的數字是16進制哦。
還有一種方法是:這個應該是XML經常使用的方法(new 2013.03.28)
'
<
>
別忘了數字後面的分號哦,而且其中的數字是十進制的
6. context的問題:
如果在一個非Activity的context裏面調用startActivity,那麼其intent必須設置:
1
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); |
否則,會報如下類似的錯誤:
1
|
Calling
startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. |
而我們還要提防系統控件中的隱性調用startActivity:
1
2
3
|
TextView
tv = new TextView(mContext); tv.setAutoLinkMask(Linkify.ALL); <br>tv.setText(content); |
當content內容中有電話號碼/郵件/URL時,並且mContext不是非Acitvity的context,而是app的context時(XXXActivity.this.getApplicationContext()),
就會出現如下的錯誤:
1
2
3
4
5
|
android.util.AndroidRuntimeException:
Calling startActivity() from outside of an Activity context
requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really
what you want? E/AndroidRuntime(10382):
at android.app.ContextImpl.startActivity(ContextImpl.java:622) E/AndroidRuntime(10382):
at android.content.ContextWrapper.startActivity(ContextWrapper.java:258) E/AndroidRuntime(10382):
at android.text.style.URLSpan.onClick(URLSpan.java:62) |
由於URLSpan.onClick中調用startActivity是由系統控制的,所以我們必須傳入activity的contex,纔不會出現如上的異常,導致程序退出。
7. 另外一個context的問題:如果你在一個單實例的對象中,有個註冊監聽器的行爲的話,那麼傳給這個單實例
對象的context,就必須是ApplicationContext了,否則會出現:receiver leak的錯誤。
8. 控件有時不能充滿整個屏幕:
1
2
3
4
5
6
|
LinearLayout
panel = new LinearLayout( this ); LinearLayout.LayoutParams
llp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); panel.setLayoutParams(llp); root.addView(panel); |
而應該是:
1
2
3
4
5
|
LinearLayout
panel = new LinearLayout( this ); LinearLayout.LayoutParams
llp = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.FILL_PARENT); root.addView(panel.
llp); |
9.按照以下的方式啓動service,但是service沒有起來
1
2
|
Intent
service = new Intent( this ,
FuncService.class); startService(service); |
很有可能是忘了在AndroidManifest.xml中註冊FuncService
1
|
<service
android:name= "com.android.example.FuncService" /> |
10.TextView中爲什麼會在有些行尾出現"..."字符,當然不是所有手機都是有問題,本來筆者剛開始也以爲可能是
手機的ROM問題,認真review了代碼,發現如下的代碼:
1
2
|
mIntroView
= (TextView) findViewById(R.id.description); mIntroView.setEllipsize(TruncateAt.END); |
問題是上面的第2行,之前是因爲要限定文本的行數,後來去掉限制,沒有去掉以上的代碼。
該行代碼會導致很多的ROM上:只要一個文本行的文字在一個手機屏幕行顯示不下的話,就自動在
行尾截斷並在行尾添加"...",而之前沒有問題是因爲:全部顯示的時候,我調用瞭如下方法:
1
|
mIntro.setMaxLines(Integer.MAX_VALUE); |
11.不要太相信工具,比如Eclipse裏面的斷點遇到多線程什麼,經常不起作用/走不到,還有就是如果語句爲空的也不會走,這時候別太早下結論斷點地方出錯了,
所以每個工程都應該有日誌的開關,通過查看日誌來確認,某個路徑是否走到或者某個變量的值,。。。
12.Java中的月份是從0開始的,所以格式化月份的時候,記得在原有的值上加1處理,如
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
Calendar
calendar = Calendar.getInstance(); if (!TextUtils.isEmpty(dateTimes)){ long
milliseconds = WLDateUtils.parseDayTime(dateTimes); calendar.setTimeInMillis(milliseconds); } final
int old_year = calendar.get(Calendar.YEAR); final
int old_month = calendar.get(Calendar.MONTH); final
int old_day = calendar.get(Calendar.DAY_OF_MONTH); mDatePickerDialog
= new DatePickerDialog( this ,
new OnDateSetListener(){ @Override public
void onDateSet(DatePicker view, int year, int
monthOfYear, int dayOfMonth) { if (year
!= old_year || monthOfYear != old_month || dayOfMonth != old_day){ String
dateTimes = String.format( "%04d-%02d-%02d" ,
year, monthOfYear
+ 1, dayOfMonth); //月份是從0開始的 } } }, old_year,
old_month, old_day); |
13.設置ListView的分割線,如果不是圖片的話,應注意順序:
1
2
3
4
5
6
7
|
mListView
= new ListView( this ); mListView.setCacheColorHint(0); mListView.setBackgroundDrawable( null ); mListView.setDivider(getResources().getDrawable(R.drawable.list_divider)); mListView.setDividerHeight(2); 其中: <drawable
name= "list_divider" > #00CCCC00</drawable> |
即 setDividerHeight 函數應該在setDivider之後,否則這個分割線無效