1. setContentView(R.layout.activity_game); 這個代碼會把 activity_game 這個 xml 里面包含的 fragment 對應的類 都進行 onCreate,然后 onCreateView,之后才執行這個語句下面的句子。
2. SharedPreferences 保存少量數據
private SharedPreferences sp;
private final static String PREFRENCE_FILE_KEY = "com.shared_preferences";
sp = getSharedPreferences(PREFRENCE_FILE_KEY, MODE_PRIVATE);
final SharedPreferences.Editor editor = sp.edit();
editor.putInt("id",1);
editor.putString("name","小熊");
editor.putInt("age",24);
editor.commit();
TextView textView = (TextView)findViewById(R.id.text);
String message = "id = " + mSharedPreferences.getInt("id",-1)
+ ",name = " + mSharedPreferences.getString("name","無")
+ ",age = " + mSharedPreferences.getInt("age",-1)+"。";
textView.setText(message);
3. println() 函數的輸出,可以在 logcat 里面,過濾填寫 system.out,即可看到了。參考:http://www.pianshen.com/article/6032179657/
4. BroadcastReceiver 可以用來針對一些事情進行廣播,比如說耳機插入,藍牙接入等等。廣播可以是標准廣播,大家都能收到,或者有序廣播,前面收到的可以截斷廣播。
5. totast 用來進行小的信息提示,存在2秒左右。
6. bundle 作為信息的載體,內部是一個 Map<string, object>, intent 持有一個 bundle,可以作為 activity 之間信息交互的橋梁。message 也可以持有 bundle,可以用於線程之間信息的交互。
7. ui 的線程作為主線程,其他的線程都是輔助線程,他們之間的通訊需要使用 handle 和 message來進行,具體參考這篇文章.
https://www.cnblogs.com/fuck1/p/5513412.html
8. onConfigurationChanged() 這個主要用於屏幕在橫屏和豎屏之間切換時候觸發。
9. Runnable 只是一個接口,其中的 run() 是執行函數體。在主線程中直接調用這個 run(),那么就是跑在主線程里面。只有使用 new Thread()來實現這個線程,然后調用 start() 來啟動新的線程,新的線程會自動運行 run() 這個函數體,運行結束之后,新線程結束。 具體參考: https://www.cnblogs.com/yuhanghzsd/p/5581918.html
10. synchronized 用來多線程中作為鎖使用。可以直接修飾方法,也可以 synchronized(tmp) 這個來鎖一個變量。都能夠使得相應的方法鎖住。在代碼塊中可以使用 notifyAll() 來喚醒其他等待鎖的線程。 參考:https://www.jianshu.com/p/35af333fdde4 和 https://www.jianshu.com/p/6999a3fa7372
11. wait() 需要在synchronized 中使用。 參考:https://blog.csdn.net/qq_30379689/article/details/53863082
12. 接口回調函數。首先定義一個接口,接口中包含方法的申明。然后在模塊類中定義一個接口變量,然后在模塊類中的方法里面對這個接口變量賦值,然后在模塊類中的方法里面調用這個接口的方法。最后在UI類中定義這個接口方法的具體實現。這樣,當模塊類執行到相應方法的時候,就會調用 UI 類中的具體實現。
MyListener.java
public interface MyListener {
// you can define any parameter as per your requirement
public void callback(View view, String result);
}
MyButton.java
public class MyButton {
MyListener ml;
// constructor
MyButton(MyListener ml) {
//Setting the listener
this.ml = ml;
}
public void MyLogicToIntimateOthers() {
//Invoke the interface
ml.callback(this, "success");
}
}
MyActivity.java
public class MyActivity extends Activity implements MyListener {
@override
public void onCreate(){
MyButton m = new MyButton(this);
}
// method is invoked when MyButton is clicked
@override
public void callback(View view, String result) {
// do your stuff here
}
}
當執行MyButton 中方法MyLogicToIntimateOthers 的時候,就會調用 MyActivity 中的 callback,參數就是 MyButton 和 "success"。實際使用中 MyLogicToIntimateOthers 這種函數經常會放到多線程的 run() 中來執行。
參考: https://stackoverflow.com/questions/994840/how-to-create-our-own-listener-interface-in-android/18585247#18585247
https://www.jianshu.com/p/e2b71caf45ee
https://blog.csdn.net/uljisang/article/details/71340301
13. 當 build 的時候,提示 Failed to delete some children. This might happen because a process has files open or has its working directory set in the target directory. 有可能是使用了 as 自帶的 terminal 窗口,並且打開了相應的目錄,只需要在 相應的命令行里面 exit 幾下,推出目錄即可。
14. 抓取log,可以使用含有 adb.exe, adbwinapi.dll, adbwinusbapi.dll 的軟件,比如說 platform-tools-latest-windows.zip,或者魯大師都可以。使用命令行打開目錄到 adb.exe 的位置,然后使用 adb devices 命令查看鏈接的設備,使用 adb shell 進入 adb模式,使用 logcat -v time >/etc/1.log 來開始保存 log,ctrl+c 停止保存 log,logcat -c 清除日志。向手機傳文件,使用 adb push c:\hosts /etc/。從手機傳文件,使用 adb pull /etc/hosts c:\。
參考:https://blog.csdn.net/u010323805/article/details/78091123
參考:https://blog.csdn.net/dodod2012/article/details/80824395
15. 串口 native 驅動方法的時候,可以參考兩篇文章關於串口參數的。
http://man7.org/linux/man-pages/man3/termios.3.html
https://blog.csdn.net/guo_wangwei/article/details/1102931#
16. consider adding at least one Activity with an ACTION-VIEW 提示這個警告,只需要在AndroidManifest.xml文件中,至少一個activity的intent-filter中添加
<action android:name="android.intent.action.VIEW" />
17. Consider adding the attribute 'android:fullBackupContent' to specify an '@xml' resource which configures which files to backup.這個警告,可以 android:allowBackup="false" 來禁止備份。如果要開啟備份,那就需要以下工作:
- 在 AndroidManifest.xml 文件中 application 里添加 android:fullBackupContent 屬性,指定一個包含備份規則的 XML 文件。
android:fullBackupContent="@xml/my_backup_rules"- 在 res/xml/ 目錄中創建一個名為 "my_backup_rules.xml" 的 XML 文件。
其中,元素指定 備份 哪些文件, 元素指定 不備份 哪些文件。
該配置文件的 XML 語法規則如下:(語法規則摘自: 數據存儲:數據備份:自動備份)
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
<include
domain=["file" | "database" | "sharedpref" | "external" | "root"]
path="string" />
<exclude
domain=["file" | "database" | "sharedpref" | "external" | "root"]
path="string" />
</full-backup-content>
在
-
指定要 備份 的 文件 或 文件夾。
默認情況下,自動備份幾乎包含所有應用程序文件。 如果指定了元素,則系統默認不再包含任何文件,並且僅備份指定的文件。 要包含多個文件,請使用多個 元素。
注意:getCacheDir(),getCodeCacheDir() 或 getNoBackupFilesDir() 返回的目錄中的文件總是被排除,即使你嘗試包含它們。
-
指定在 備份 期間要 排除 的 文件 或 文件夾。
以下是通常從備份中排除的一些文件:
Ⅰ. 具有設備特定標識符的文件,由服務器頒發或在設備上生成。 例如,Google Cloud Messaging(GCM)需要在每次用戶在新設備上安裝您的應用程序時生成注冊令牌。 如果舊的注冊令牌已恢復,應用程序可能會出現意外。
Ⅱ. 賬戶憑證或其他敏感信息。 考慮要求用戶在第一次啟動還原的應用程序時重新認證,而不是允許在備份中存儲此類信息。
Ⅲ. 與應用程序調試相關的文件,如即時運行文件。 要排除即時運行文件,請添加規則 <exclude domain =“file”path =“instant-run”/>
Ⅳ. 導致應用超出 25MB 備份配額的大文件。
注:如果你的配置文件指定了這兩個元素,則備份 包含由元素捕獲的所有內容減去 元素中命名的資源。 換句話說, 優先。
每個元素必須包含以下 2 個屬性:
Ⅰ. domain:指定資源的位置。
此屬性的有效值包括以下內容:
- root:存儲屬於此應用程序的所有私有文件的文件系統上的目錄。
- 文件:由 getFilesDir() 返回的目錄。
- 數據庫:由 getDatabasePath() 返回的目錄。使用 SQLiteOpenHelper 創建的數據庫存儲在此處。
- sharedpref:存儲 SharedPreferences 的目錄。
- 外部由 getExternalFilesDir() 返回的目錄。
注:你無法備份這些位置之外的文件。
Ⅱ. path:指定要從備份中包含或排除的文件或文件夾。 注意:
- 此屬性不支持通配符或正則表達式語法。
- 您可以使用 "." 引用當前目錄,但是,出於安全考慮,您無法引用父目錄。
- 如果指定目錄,則該規則適用於目錄中的所有文件和遞歸子目錄。
參考:https://blog.csdn.net/u013719138/article/details/79276370
18. Synchronization on a non-final field. 同步的 object 最好是用 final 的。
19. android studio 不用 e.printStackTrace();使用 Log.e(TAG,Log.getStackTraceString(e)) 來打印異常。
20. 數組復制,使用 System.arraycopy。Arrays.copyOf 和 Arrays.copyOfRange 會創建一個新的數組並返回。 定義數組的時候,可以使用 .clone() 的方法來生成另外一個數組的拷貝。 當然也可以實現Cloneable接口,並重寫clone方法,注意一個類不實現這個接口,直接使用clone方法是編譯通不過的。
21. 布局中分割線可以用 linearlayout.divider 來設置。具體參考:https://blog.csdn.net/qq_36523667/article/details/80184646
android:gravity 讓器件向某個方向偏。
22. 當某個繼承類內部重寫了回調事件的處理方法,那么這個類就不需要用 setxxxListener 的方法來綁定一個監聽事件類,直接使用自己內部的回調方法就可以。但是注意:在 xml 里面一定要寫這個新的類的全名
public class MyButton extends Button{
private static String TAG = "呵呵";
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
//重寫鍵盤按下觸發的事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
super.onKeyDown(keyCode,event);
Log.i(TAG, "onKeyDown方法被調用");
return true;
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MyActivity">
<example.jay.com.mybutton.MyButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按鈕"/>
參考:https://www.runoob.com/w3cnote/android-tutorial-callback-event-handle.html
23. 回調函數的返回值是 true 的時候,說明事件已經處理完成,如果是 false,那么還要繼續傳播,直到觸發 activity 的處理函數。優先級是: setxxxListener 指定的監聽器內的回調方法 --> 繼承 view 中重寫的回調方法 --> activity 中重寫的回調方法。
參考: https://www.runoob.com/w3cnote/android-tutorial-callback-event-handle.html
24. 最近用到handle在線程中改變UI,會跟給出“This Handler class should be static or leaks might occur”的警告.解決方法如下:
static class MyHandler extends Handler {
//注意下面的“PopupActivity”類是MyHandler類所在的外部類,即所在的activity
WeakReference<PopupActivity> mActivity;
MyHandler(PopupActivity activity) {
mActivity = new WeakReference<PopupActivity>(activity);
}
@Override
public void handleMessage(Message msg) {
PopupActivity theActivity = mActivity.get();
switch (msg.what) {
//此處可以根據what的值處理多條信息
case 0x0001:
//這里可以改變activity中的UI控件的狀態
theActivity.textView.setText(R.string.hello_world);
break;
}
case 0x0002:
//這里可以改變activity中的UI控件的狀態
theActivity.textView.setText(R.string.welcome);
break;
/*這里可以有多條要處理信息的操作*/
/*... ...*/
}
}
};
//實例化一個MyHandler對象
MyHandler testHandler = new MyHandler(this);
private void test1() {
//這里發送了一個空消息,空消息的what值是0x0001
testHandler.sendEmptyMessage(0x0001);
}
private void test2() {
//這里發送了一個空消息,空消息的what值是0x0001
testHandler.sendEmptyMessage(0x0002);
}
參考: https://www.cnblogs.com/welhzh/p/3585478.html
25. async 中的 doInBackground 的返回值用於 onPostExecute 的參數,做為線程最后的收尾方法。
26. 可以讓所有的 activity 繼承自一個自定義的 baseactivity 類,在這個類的 oncreate 方法中添加 log.d("BaseActivity", getClass().getSimpleName()); 這樣每當一個 activity 啟動時都會打印具體的類。
27. 可以創建一個 activity 的管理類,每當一個 activity 啟動,就向 list 中增加,推出,就減少。可以通過 對這個 list 中所有的 activity 使用 finish 來退出所有的 activity。需要在 baseactivity 中的 oncreate 方法里面添加 addactivity 的調用,在 onDestory 中添加 removeactivity 的調用,這個可以在任何一個 activity 中調用 finishall 來關閉所有,從而推出 app。還可以設置雙擊返回鍵退出 app。
參考: https://www.runoob.com/w3cnote/android-tutorial-activity-start.html
https://www.jianshu.com/p/0b979a69756c
28. activity 過渡動畫,參考:https://www.runoob.com/w3cnote/android-tutorial-activity-start.html
29. bundle 傳遞數據,需要小於 0.5MB,如果大,會報 TransactionTooLargeException 異常。
30. activity 全屏的方法:
- oncreate 中調用 getActionBar.hide();
- 把 requestWindowFeature(Window.FEATURE_NO_TITLE);放在super.onCreate(savedInstanceState);前面
- androidmanifest.xml 中的 theme 里面,在需要全屏的Activity的標簽內設置 theme = @android:style/Theme.NoTitleBar.FullScreen
31. onWindowFocusChanged 方法可以用來監控 activity 是否加載完畢。
32. activity 正常是保存在 task 里面的。按 home ,會返回桌面和調出前段時間使用過的 task 列表。可以設置 activity 的屬性,讓activity 獨占 task 或者其他可能。
完整的 activity manager 類,
參考:https://www.runoob.com/w3cnote/android-tutorial-activity-intro.html
33. java.lang.IllegalArgumentException: Service Intent must be explicit: Intent 這個報警只需要添加一句代碼:
intent.setPackage(getPackageName());
參考:https://www.cnblogs.com/brucemengbm/p/7234128.html
34. activity 和 service 通信,需要使用 自定義的 binder 類,把需要暴露的方法寫到這個類中,然后重寫 service 的 onBind 方法,把這個 binder 對象 return 回去。然后在 activity 中實例化一個 serviceconnection 對象,重寫 onserviceconnected 方法,獲取這個 binder 對象,然后調用相關方法即可。
參考: https://www.runoob.com/w3cnote/android-tutorial-service-1.html
https://www.runoob.com/w3cnote/android-tutorial-service-2.html
35. getNotification 方法廢棄后,可以用 build 來代替。
startForeground(1, localBuilder.build());
還有別忘了許可
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
還有別忘了在onDestroy里面調用stopForeground。
36. 把 service 綁定到 alarm 上面后,就可以執行定時的后台服務。具體參考:
https://www.runoob.com/w3cnote/android-tutorial-service-2.html
37. new --> aidl --> aidl file 新建一個 aidl 文件后,要記得 rebuild project,否則不能生成對應的 java 文件。還有注意 aidl 里面不要有中文,否則可能生成的 java 是空的。
38. bindService 返回 false。解決從如下幾個方面來看:
- aidl 文件:IPerson.aidl,所在的包是 com.example.aidl ; service類是 AidlService,所在的包是 com.example.aidlservice ; client 類是 MainActivity,所在的包是 com.jay.example.aidlclient。把 aidl 文件所在的文件夾,從 server 中整個復制到 client 中。
- AidlService 中 onBind() 注意要 return IBinder 對象。
- service 的 配置文件中
這里面的 name 可以自由設置。 - client 的 MainActivity 中 Intent service = new Intent("android.intent.action.AIDLService123"); 注意這里面的參數是和 service 配置文件中的 name 一致。
- client 的 MainActivity 中 service.setPackage("com.example.aidlservice"); 注意這個參數是 service 中我們自定義的類 AidlService 所在的包名稱。
達到上面幾點,基本就 bindservice 就沒有問題了。
參考: https://www.runoob.com/w3cnote/android-tutorial-service-3.html
https://blog.csdn.net/u012810034/article/details/71523847
39. 對於沒有 activity 的 server 想要運行調試,只需要在 android studio 中 app 運行配置中選擇 launch: nothing 即可。
參考: https://blog.csdn.net/qq_36792930/article/details/91041904
40. parcelable 實現的時候, newArray() 方法中 return new T[0] 改為 return new T[size]。
具體參考: https://www.cnblogs.com/renqingping/archive/2012/10/25/Parcelable.html
41. aidl 報錯誤 couldn't find import for class。解決如下:
- aidl 文件: ISalary.aidl 所在的包是 com.runoob.aidl123 , ISalary.aidl 是實質性的 aidl 文件。里面的方法申明,參數中包含了 Person 和 Salary 類。需要 import 相應的類。
- Person.java,salary.java 里面實現了 Parcelable, 所在的包是 com.runoob.classserver。
- 建立 Person.aidl 文件,里面兩句代碼: package com.runoob.classserver; 注意這個必須和 Person.java 是同一個包名。parcelable Person; 這個表明是序列化的 Person。
- 仿照 Person.aidl,建立 Salary.aidl。
主要注意,java 和 aidl 同名的文件,包名也要一致不然找不到。
42. 服務通信,也可以不使用 aidl,直接用 transact 來實現。因為 aidl 本來就是在 transact 上面封裝了一層,所以直接用 transact 可以不用 aidl 文件,就是自己實現, 代碼稍微難看一點。但是 配置文件里面的
這個是少不了的。
具體參考 : https://www.runoob.com/w3cnote/android-tutorial-service-3.html
https://blog.csdn.net/lmj623565791/article/details/38461079#t9
43. 可以使用 maven 來簡化一些依賴。
參考: https://www.cnblogs.com/lixiangyang521/p/7760754.html
https://blog.csdn.net/kdsde/article/details/90915634
44. 廣播分為動態和靜態兩種。動態不需要在配置文件中注冊,靜態需要修改配置文件,進行注冊。動態廣播,必須軟件打開才能接收。靜態廣播,開機就能夠接收廣播了。
45. 自定義廣播,要注意,發送app 中的 sendBroadcast(new Intent("com.example.broadcasttest.MY_BROADCAST")); 需要和接收app 的配置文件中的
相對應。
參考: https://www.runoob.com/w3cnote/android-tutorial-broadcastreceiver.html
46. 在你的activity動作完成的時候,或者Activity需要關閉的時候,調用 Activity.finish()。 fininsh 方法調用的時候,系統移除了 activity,但並不會立刻銷毀,所以,過一段時間后,系統才會調用 Activity.onDestory() 來回收空間。
並且不同階段調用 finish,也會調用到不同的函數。
Calling finish() in onCreate(): onCreate() -> onDestroy()
Calling finish() in onStart() : onCreate() -> onStart() -> onStop() -> onDestroy()
Calling finish() in onResume(): onCreate() -> onStart() -> onResume() -> onPause() -> onStop() -> onDestroy()
參考:https://blog.csdn.net/soulmeetliang/article/details/62280342
https://blog.csdn.net/weixin_30654419/article/details/95311721
https://blog.csdn.net/hyz5159037/article/details/8151463
https://blog.csdn.net/u012359453/article/details/89252260
https://blog.csdn.net/houdezaiwu01/article/details/51526607?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
47. 哪個 activity 是首個頁面,像下面那樣來設置:
android.intent.action.MAIN:決定應用的入口Activity,也就是我們啟動應用時首先顯示哪一個Activity。
android.intent.category.LAUNCHER:表示activity應該被列入系統的啟動器(launcher)(允許用戶啟動它)。Launcher是安卓系統中的桌面啟動器,是桌面UI的統稱。
參考:https://www.cnblogs.com/zhaogaojian/p/9480217.html
48. 在 app 內部進行廣播可以使用本地廣播, LocalBroadcastManager, 還需要 IntentFilter 配合一起使用。 別忘了 registerReceiver 和 onDestroy 中的 unregisterReceiver 。
AlertDialog 使用 setType 時候, 使用 WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW + 3 來代替廢棄的 SYSTEM_ALERT_WINDOW 。 還有別忘了要注冊許可:uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"。
當在廣播中設置監聽器的時候,如果要使用 Intent,需要類似下面的方法:
Intent intent = new Intent(context, LoginActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
參考:
https://www.runoob.com/w3cnote/android-tutorial-broadcastreceiver-2.html
49. 當需要監聽 sd 卡的時候,因為 sd 卡是開機后才掛載的,所以注冊時候,要分開來些。
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
<intent-filter>
<action android:name="ANDROID.INTENT.ACTION.MEDIA_MOUNTED"/>
<action android:name="ANDROID.INTENT.ACTION.MEDIA_UNMOUNTED"/>
<data android:scheme="file"/>
</intent-filter>
</receiver>
android 常用廣播參考: https://www.runoob.com/w3cnote/android-tutorial-broadcastreceiver-2.html
50. 調試的時候,想要看到 /data/data 這種隱藏文件夾,需要在 android studio 中點擊 右下角的 Device file explorer,即可看到所有文件,然后找到相應的文件后,右鍵另存為即可保存到 pc 上面。或者 View > Tool Windows > Device File Explore。
參考: https://www.jianshu.com/p/535ba644cbd3
51. 獲取系統里面的圖片資源,或者文件資源,使用 contentprovider。也可以把自己的數據包裝一下,實現為 documentprovider,給其他應用使用。
參考:https://www.runoob.com/w3cnote/android-tutorial-contentprovider-2.html
52. activity 正常可以通過 startActivity 這樣顯式啟動,也可以通過隱式啟動。隱式的方法是:指定Intent的Action,Data,或Category,當我們啟動組件時, 會去匹配AndroidManifest.xml相關組件的Intent-filter,逐一匹配出滿足屬性的組件,當不止一個滿足時, 會彈出一個讓我們選擇啟動哪個的對話框。
new Intent(oneActivity.this, secondActivity.class); 第一個參數是上下文,就是 content,也就是包名,第二個參數是類名,這樣包名+類名就是唯一限定類了。
一個 intent 的只有一個 action,但是可以有多個 category.
data, type 在配置文件中 data 標簽下面設置。
extras 用於數據交換時的 bundle 類型。
flag 用於 activity 如何啟動,以及啟動后如何對待。
返回桌面:
it.setAction(Intent.ACTION_MAIN);
it.addCategory(Intent.CATEGORY_HOME);
打開網頁:
it.setAction(Intent.ACTION_VIEW);
it.setData(Uri.parse("http://www.baidu.com"));
隱式啟動的時候,比較 intent 中的 action 和 category,action 可以是系統定義的,也可以是自定義的。 category 自定義的時候,要注意,還要添加上 DEFATLT,不然會報錯。如下:
Intent it = new Intent();
it.setAction("my_action");
it.addCategory("my_category");
startActivity(it);
<activity android:name=".SecondActivity"
android:label="第二個Activity">
<intent-filter>
<action android:name="my_action"/>
<category android:name="my_category"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
常用 intent 參考: https://www.runoob.com/w3cnote/android-tutorial-intent-base.html
action 可以從這里查看: sdk-->docs-->reference-->android--->content--->Intent.html , 從這個Constants開始就是了。
53. intent 傳遞數組,使用putStringArray 和 getStringArray 這樣的。
intent 傳遞集合 list:
- List<基本數據類型或String>
intent.putStringArrayListExtra(name, value)
intent.putIntegerArrayListExtra(name, value)
intent.getStringArrayListExtra(name)
intent.getIntegerArrayListExtra(name)
- List< Object>將list強轉成Serializable類型,然后傳入(可用Bundle做媒介)Object類需要實現Serializable接口
putExtras(key, (Serializable)list)
(List<Object>) getIntent().getSerializable(key)
- 在外層套個 list 的殼子。
intent 傳遞對象: 將對象轉換為Json字符串或者通過Serializable,Parcelable序列化 不建議使用Android內置的摳腳Json解析器,可使用fastjson或者Gson第三方庫!
Parcelable 可以使用插件: Android Parcelable code generator 來自動生成。
Bitmap 本身實現了Parcelable, 直接傳遞即可。
或者直接使用 application 級別的全局變量,給整個 app 的 activity 使用。但是要注意:如何按 home 按鍵,讓 app 處於后台,時間長了,可能會被殺后台。這時候讓后台任務回到前台,只有 app 最后一個 activity 是保留的,整個app其他內容都是重新創建的,這樣會導致全局變量被初始化了。所以這樣的情況最好做成本地存儲。
還可以使用單例模式傳遞,只是要注意線程安全。
參考:https://www.runoob.com/w3cnote/android-tutorial-intent-pass-data.html
54. 'com.github.dcendents.android-maven' not found.
錯誤原因:導入了一個module 其build.gradle引用了
apply plugin: 'com.github.dcendents.android-maven'
導入后項目提示
Plugin with id 'com.github.dcendents.android-maven' not found
解決方式:在project目錄下的build.gradle對應位置添加
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
請在這里查對應的maven-gradle-plugin版本, https://github.com/dcendents/android-maven-gradle-plugin
Plugin Version | Plugin Name | Dependency Information | Gradle Version |
---|---|---|---|
1.0 | android-maven | com.github.dcendents:android-maven-plugin:1.0 | 1.8+ |
1.1 | android-maven | com.github.dcendents:android-maven-plugin:1.1 | 1.12+ |
1.2 | com.github.dcendents.android-maven | com.github.dcendents:android-maven-plugin:1.2 | 2.2+ |
1.3 | com.github.dcendents.android-maven | com.github.dcendents:android-maven-gradle-plugin:1.3 | 2.4+ |
1.4.1 | com.github.dcendents.android-maven | com.github.dcendents:android-maven-gradle-plugin:1.4.1 | 2.14+ |
1.5 | com.github.dcendents.android-maven | com.github.dcendents:android-maven-gradle-plugin:1.5 | 3.0+ |
2.0 | com.github.dcendents.android-maven | com.github.dcendents:android-maven-gradle-plugin:2.0 | 4.1+ |
2.1 | com.github.dcendents.android-maven | com.github.dcendents:android-maven-gradle-plugin:2.1 | 4.6+ |
參考: https://blog.csdn.net/qq_23089525/article/details/77935014
55. 同一個 activity 中的不同 fragment 之間傳遞數據。可以在 activity 里面建立方法,然后在 fragment 中調用相應的方法,類似:
((MainActivity)getActivity()).setValueResultData(0x123);
參考: https://blog.csdn.net/hd12370/article/details/82825077
https://blog.csdn.net/harvic880925/article/details/44131865
https://blog.csdn.net/harvic880925/article/details/44966913
56. activity 返回數據給上一個 activity,可以這樣寫
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first);
gotoSecondBtn = findViewById(R.id.goto_second_btn);
//對按鈕進行監聽
gotoSecondBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//使用intent進行跳轉
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
//啟動跳轉,這里使用startActivityForResult()方法,這個方法會在跳轉到的活動頁面銷毀時,返回一個數據給上一個活動
/**
* param1:intent
* param2:請求碼,用於回調時判斷數據的來源
*/
startActivityForResult(intent, 1);
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.e(TAG, "onActivityResult1: "+data );
switch (resultCode) {
//下面的1為startActivityForResult(intent, 1);中的1
case 1:
//這里的1為setResult(1, intent);中的1
if (resultCode==1){
String str = data.getStringExtra("hello");
Log.e(TAG, "onActivityResult2: "+str );
String str2 = data.getStringExtra("hi");
Log.e(TAG, "onActivityResult3: "+str2 );
}
break;
default:
break;
}
}
secondBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//創建Intent對象
Intent intent = new Intent();
//通過put()以鍵值對的方式賦值
intent.putExtra("hi", "hi FirstActivity");
//通過setResult()方法向上一個活動返回結果 param1:處理結果代號
setResult(1, intent);
finish();
}
});
@Override
public void onBackPressed() {
// super.onBackPressed();
Intent intent = new Intent();
intent.putExtra("hello","Hello FirstActivity");
setResult(1,intent);
finish();
}
參考: https://blog.csdn.net/shaochen2015821426/article/details/80155457
57 genymotion 模擬器不適合調試 sqlite,還是需要真機調試。 調試的時候,可以使用 adb shell 來進入真機,然后 cd 到數據庫目錄,使用 sqlite3 my.db 來進入數據庫,.table 查看表, select * from person,查看 person 的表。.quit:退出數據庫的編輯, .exit:退出設備控制台。
sqlite3如何退出...>狀態 : 只需要執行一條 sql 語句帶分號即可, 或者直接輸入分號,也能退出這個狀態。
MainActivity.this.getDatabasePath("my.db").toString() 可以通過這個獲得當前對應的數據庫存放的位置。
參考: https://blog.csdn.net/liubingzhao/article/details/47041735
https://www.cnblogs.com/wenjiang/archive/2013/05/28/3100860.html
https://www.runoob.com/w3cnote/android-tutorial-sqlite-intro.html
58 is not an enclosing class,
public class A {
public class B {
}
};
需要實例B類時,按照正常邏輯是,
A.B ab = new A.B();
但是實際上應該這樣寫:
A a = new A();
A.B ab = a.new B();
沒有靜態(static)的類中類不能使用外部類進行.操作,必須用實例來進行實例化類中類.
參考: https://www.cnblogs.com/royi123/p/5510867.html
59 vector 中的數據需要打印,可以先生成 array,然后再把 array toString 一下即可。
Vector<Byte> adc = ack.getAdc();
Log.d(TAG, Arrays.toString(adc.toArray()));
60 sqlite3 獲取最后一條記錄,有幾種方法:
String find = "SELECT * FROM table";
Cursor cursor = db.rawQuery(find, null);
if (cursor.moveToLast()) {
...
}
參考: https://zhidao.baidu.com/question/538870505.html
https://www.oschina.net/question/1391382_132162
https://www.cnblogs.com/clyz/p/3411127.html
61. sqlite 保存數組
String insert = "INSERT INTO " +
"sampleAdc(adcNum, adcBuf) " +
"values(?, ?)";
byte[] tmp = {0x12, 0x34, 0x56, 0x78};
Object[] args = new Object[]{adcNum, tmp};
db.execSQL(insert, args);
String find = "SELECT * FROM sampleAdc WHERE adcNum = ?";
Cursor cursor = db.rawQuery(find, new String[]{Long.toString(adcNum, 16)});
if (cursor.moveToFirst()) {
byte[] adc = cursor.getBlob(cursor.getColumnIndex("adcBuf"));
上面代碼就是 sqlite 保存二進制和字符串之間的差別地方。
參考 https://www.cnblogs.com/zhoug2020/p/3723859.html
https://blog.csdn.net/xiaoaid01/article/details/17998013
https://www.runoob.com/w3cnote/android-tutorial-sqlite-2.html
https://blog.csdn.net/calvin367/article/details/38020081/
62. application 全局變量
public class SupertestApp extends Application 在這個新的類里面至少要實現 onCreate.
然后在 AndroidManifest.xml 里面 <application 下面修改 android:name="SupertestApp"。這樣在 activity 的類里面就可以使用 ((SupertestApp)getApplication()).findInfo(adcNum) 這樣的語句調用 SupertestApp 里面的函數 findInfo。在 fragment 里面可以使用 ((SupertestApp)getActivity().getApplication()).getCurrentSampleInfo() 這樣的語句來調用 application 級別的函數。
參考: https://www.cnblogs.com/maoIT/p/3835833.html
63. radiobutton 是個虛影,很有可能是因為創建 adpater 的時候,不是給的 activity,而是 application,這樣就會是個虛影。
這樣在 getview 這個方法里面 convertView 下面兩種賦值方法都可以。
convertView = activity.getLayoutInflater().inflate(R.layout.project_manage_list_view_item, null);
convertView = activity.getLayoutInflater().inflate(R.layout.project_manage_list_view_item,
parent, false);
下面兩種方法都不行, context 是 application的。 不管是 getApplicationContext 還是 getApplication 都不行。
convertView = LayoutInflater.from(context).inflate(R.layout.project_manage_list_view_item,
parent, false);
convertView = LayoutInflater.from(context).inflate(R.layout.project_manage_list_view_item, null);
63. listview 需要分頁顯示的時候,主要在 adpater 里面的 getCount 這個方法里面修改,這個函數是返回當前頁面有多少個條目。 還要修改 getView 方法,這個方法是用來顯示當前頁面的。
參考:https://www.cnblogs.com/wangfeng520/p/6178455.html
64. button 和 layout 設置背景如下:
prevPager.setBackgroundColor(getResources().getColor(R.color.backgroundColorSecond));
prevLayout.setBackground(getResources().getDrawable(R.drawable.semicircle_shape_button_disable));
65. 使用 libaums 來操作 u 盤碰到 Unsuccessful Csw status: 1,和 分區返回 0 的情況。
Unsuccessful Csw status: 1 有說法是 需要在申請權限后,延遲 1 - 3 秒在 init 設備。
參考: https://github.com/magnusja/libaums/issues/124
分區返回0 有說法是在使用 usb 讀卡器的情況下出現。 implementation 'com.github.mjdev:libaums:0.5.5' 這個版本會出現這個情況。
參考: https://github.com/magnusja/libaums/issues/163
嘗試升級到高版本。 implementation 'me.jahnen:libaums:0.7.5',然后在 device.init() 之前增加 Thread.sleep(1000),正常的 u盤和讀卡器都可以工作了。 也可以考慮使用 countdown 來實現延時功能。
操作u盤的代碼可以參考:
https://blog.csdn.net/viking_xhg/article/details/81215297
https://blog.csdn.net/true100/article/details/77775700
https://blog.csdn.net/qq_31939617/article/details/80447276
https://github.com/magnusja/libaums
65. 格式化輸出,可以使用 Formatter 構造格式。
兩位小數的浮點數格式輸出可以如下:
Formatter formatter = new Formatter();
formatter.format("%.2f - %.2f", rangeValue.get(0), rangeValue.get(1));
range.setText(formatter.toString());
輸出結果類似: 1.00 - 2.00
參考: https://blog.csdn.net/cuixianlong/article/details/78583186
66. 在循環中,讓多個字符串連接,最后需要刪除最后一個分隔符的時候。可以使用
StringBuilder builder = new StringBuilder("手機號1,手機號2,手機號3,");
String result = builder.deleteCharAt(builder.length() - 1).toString();
參考: https://blog.csdn.net/qq_20552525/article/details/92831500
67. 多個 map 合並為一個 map
Map<String, String> map1 = new HashMap<String, String>();
map1.put("one", "一");
map1.put("two", "二");
map1.put("three", "三");
Map<String, String> map2 = new HashMap<String, String>();
map1.put("ten", "十");
map1.put("nine", "九");
map1.put("eight", "八");
// 合並
Map<String, String> combineResultMap = new HashMap<String, String>();
combineResultMap.putAll(map1);
combineResultMap.putAll(map2);
參考: https://www.cnblogs.com/han-1034683568/p/10175466.html
68. 讀取當前系統時間
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date(System.currentTimeMillis());
String dateTime = simpleDateFormat.format(date);
參考: https://blog.csdn.net/huangshenshen_/article/details/57161724
69. 操作 sqlite 數據庫
插入操作:
public void insertSample(SampleInfo info) {
SQLiteDatabase db = superTestDBOpenHelper.getWritableDatabase();
String insert = "INSERT INTO " +
"sampleInfo(id, name, sex, age, examinationclerk, projectId, projectCol, " +
"ratio, gradient, concentration, conclusion, sampleTime, visible, adcNum) " +
"values(?, ?, ?, ?, ?, ?, ?, " +
"?, ?, ?, ?, ?, ?, ?)";
String[] param = info.getInfo();
Log.d(TAG, "insertSample: " + info.toString());
db.execSQL(insert, param);
}
查找操作:
public SampleInfo findSample(String id) {
//SampleInfo info = new SampleInfo();
SQLiteDatabase db = superTestDBOpenHelper.getReadableDatabase();
String find = "SELECT * FROM sampleInfo WHERE id = ?";
Cursor cursor = db.rawQuery(find, new String[]{id});
if (cursor.moveToFirst()) {
String name = cursor.getString(cursor.getColumnIndex("name"));
String sex = cursor.getString(cursor.getColumnIndex("sex"));
String age = cursor.getString(cursor.getColumnIndex("age"));
String clerk = cursor.getString(cursor.getColumnIndex("examinationclerk"));
String[] param = new String[] {id, name, sex, age, clerk};
info.setPersonalInfo(param);
String projectId = cursor.getString(cursor.getColumnIndex("projectId"));
String projectCol = cursor.getString(cursor.getColumnIndex("projectCol"));
param = new String[] {projectId, projectCol};
info.setProjectInfo(param);
String ratio = cursor.getString(cursor.getColumnIndex("ratio"));
String gradient = cursor.getString(cursor.getColumnIndex("gradient"));
String concentration = cursor.getString(cursor.getColumnIndex("concentration"));
String unit = cursor.getString(cursor.getColumnIndex("unit"));
String conclusion = cursor.getString(cursor.getColumnIndex("conclusion"));
String sampleTime = cursor.getString(cursor.getColumnIndex("sampleTime"));
String visible = cursor.getString(cursor.getColumnIndex("visible"));
param = new String[] {ratio, gradient, concentration, unit, conclusion, sampleTime, visible};
info.setResult(param);
String adcNum = cursor.getString(cursor.getColumnIndex("adcNum"));
param = new String[] {adcNum};
info.setAdcNum(param);
SampleInfo info = getInfo(cursor);
Log.d(TAG, "findSample: " + info.toString());
cursor.close();
return info;
}
cursor.close();
return null;
}
插入 blob 操作:
public void insertAdc(long adcNum, byte[] adc) {
SQLiteDatabase db = superTestDBOpenHelper.getWritableDatabase();
String insert = "INSERT INTO " +
"sampleAdc(adcNum, adcBuf) " +
"values(?, ?)";
Object[] args = new Object[]{Long.toString(adcNum, 16), adc};
Log.d(TAG, "insertAdc: adcNum = " + Long.toString(adcNum, 16) + ", adcBuf = " +
Arrays.toString(adc));
db.execSQL(insert, args);
}
查找 blob 操作:
public byte[] findAdc(long adcNum) {
//SampleInfo info = new SampleInfo();
SQLiteDatabase db = superTestDBOpenHelper.getReadableDatabase();
String find = "SELECT * FROM sampleAdc WHERE adcNum = ?";
Cursor cursor = db.rawQuery(find, new String[]{Long.toString(adcNum, 16)});
if (cursor.moveToFirst()) {
byte[] adc = cursor.getBlob(cursor.getColumnIndex("adcBuf"));
Log.d(TAG, "findAdc: " + Arrays.toString(adc));
cursor.close();
return adc;
}
cursor.close();
return null;
}
刪除操作
public void deleteProject(int projectId, int batchId, String batchCode,
String projectName) {
SQLiteDatabase db = superTestDBOpenHelper.getWritableDatabase();
String delete = "DELETE FROM projectConfig WHERE " +
"projectId = ? AND batchId = ? AND batchCode = ? AND projectName = ?";
String[] args = new String[] {Integer.toString(projectId), Integer.toString(batchId),
batchCode, projectName};
Log.d(TAG, "deleteProject: projectId = " + projectId + ", batchId = " +
batchId + ", batchCode = " + batchCode + ", projectName = " + projectName);
db.execSQL(delete, args);
}
70. string 與 byte[] 互相轉換
byte[] detalArray;
try {
detalArray = detail.getBytes("utf-8");
} catch (Exception e) {
Log.d(TAG, Log.getStackTraceString(e));
return;
}
byte[] detailArray = cursor.getBlob(cursor.getColumnIndex("detail"));
String detail = null;
try {
detail = new String(detailArray, "utf-8");
} catch (Exception e) {
Log.d(TAG, Log.getStackTraceString(e));
return null;
}
參考: https://www.cnblogs.com/Marydon20170307/p/9273724.html
71. activity 調用 fragment 中的方法。
Fragment fragmentPushMealHistory = new pushMealHistoryFragment(ctxt);
((pushMealHistoryFragment)fragmentPushMealHistory).updateGridview();
參考: https://www.cnblogs.com/kunyashaw/p/4994963.html
72. listview 倒序顯示。
- 可以在 list 插入的時候,選擇 addFirst,每次都是把最新的插在最前面。
- 也可以在 list 插入的時候,選擇 add,最后使用,Collections.reverse(list); 把整個列表倒序。
- 也可以在 adapter 的 getView 中,顯示的時候,在 list.get(i) 的時候,給 i 賦值為 list.size - 1 - position.
73. 輸出指定寬度的字符串,不足的補空格。
String name = String.format("%-12s", name);
74. map 遍歷可以使用
for(Map.Entry<String, String> entry : map.entrySet() {
String mapKey = entry.getKey();
String mapValue = entry.getValue();
}
上面這種適合 key 和 value 都需要用到的場合,如果只需要 key 或者 value,可以下面這種。
for(String key : map.keySet())
for(String value : map.values())
不要在 for 中通過 map.get(key) 這種方式,通過查詢 key 來取值。這樣效率會比較低,應該使用第一種。
參考: https://www.cnblogs.com/damoblog/p/9124937.html
75. 查看 layout 的 height 和 width.
final LinearLayout listLayout = view.findViewById(R.id.pm_project_data_list_layout);
listLayout.post(new Runnable() {
@Override
public void run() {
Log.d(TAG, "list view height = " + listLayout.getHeight());
}
});
返回以像素為單位,想要和 dp 轉換,需要下面這樣。 注意: 這個未經測試。
public int pxToDp(int px)
{
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
int dp = Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
return dp;
}
public int dpToPx(int dp)
{
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}
要將像素轉換為dpi,請使用此公式px = dp *(dpi / 160)
據說下面代碼可以獲得運行時尺寸。
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int wwidth = displaymetrics.widthPixels;
參考: http://androidcookie.com/getheight()px還是dpi?.html
https://www.cnblogs.com/tc310/p/10739247.html
https://www.jianshu.com/p/422ef0d75943
76. 使用 http,可以使用 okHttp,在 minSdkVersion 16 的情況下,只能使用 3.12.x 的版本,3.13.x 會要求最低版本是 24.具體的版本可以參考 https://square.github.io/okhttp/changelog_3x/
正常的添加依賴如下:
dependencies {
//...
//OkHttp
implementation 'com.squareup.okhttp3:okhttp:3.14.2'
implementation 'com.squareup.okio:okio:1.17.4'
}
77. 系統時間從字符串解析回 Date。
public static Date strToDateLong(String strDate) {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ParsePosition pos = new ParsePosition(0);
Date strtodate = formatter.parse(strDate, pos);
return strtodate;
}
參考: https://www.cnblogs.com/kevin-chen/p/7239650.html
78. 獲得系統唯一 ID
instrument_number = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
參考: https://www.cnblogs.com/xieping/p/4784564.html
79. sqlite 清除表,不僅僅清除表本身,如果表主鍵是自增的,還要清除自增。
DELETE FROM TableName
DELETE FROM sqlite_sequence WHERE name = 'TableName'
也可以設置 sqlite_sequence 為 0
UPDATE sqlite_sequence SET seq = 0 WHERE name = 'TableName'
如果所有表的主鍵自增都刪除,可以
DELETE FROM sqlite_sequence
參考: https://blog.csdn.net/qq_26462135/article/details/74295905
https://www.oschina.net/question/577276_60172
80. okhttp get 和 pos json
//創建OkHttpClient對象
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10,TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.build();
final Request request = new Request.Builder()
.url("http://172.20.192.168:8080/getbookByFrom?name=android基礎&price=50")//請求的url
.get()//設置請求方式,get()/post() 查看Builder()方法知,在構建時默認設置請求方式為GET
.build(); //構建一個請求Request對象
//創建/Call
Call call = okHttpClient.newCall(request);
//加入隊列 異步操作
call.enqueue(new Callback() {
//請求錯誤回調方法
@Override
public void onFailure(Call call, IOException e) {
System.out.println("連接失敗");
}
//異步請求(非主線程)
@Override
public void onResponse(Call call, Response response) throws IOException {
if(response.code()==200) {
System.out.println(response.body().string());
}
});
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10,TimeUnit.SECONDS)
.readTimeout(20, TimeUnit.SECONDS)
.build();
Book book = new Book();
book.setName("android基礎");
book.setPrice(59);
//使用Gson 添加 依賴 compile 'com.google.code.gson:gson:2.8.1'
Gson gson = new Gson();
//使用Gson將對象轉換為json字符串
String json = gson.toJson(book);
//MediaType 設置Content-Type 標頭中包含的媒體類型值
RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
, json);
Request request = new Request.Builder()
.url("http://172.20.192.168:8080/getbookByJson")//請求的url
.post(requestBody)
.build();
//創建/Call
Call call = okHttpClient.newCall(request);
//加入隊列 異步操作
call.enqueue(new Callback() {
//請求錯誤回調方法
@Override
public void onFailure(Call call, IOException e) {
System.out.println("連接失敗");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println(response.body().string());
}
});
參考: https://blog.csdn.net/mp624183768/article/details/80905783
https://www.jianshu.com/p/aaa87e8ad9eb
https://www.jianshu.com/p/d006bc55bca9
81. popwindow 中的 spinner 點擊崩潰。
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
解決方法很簡單,在 spinner 的屬性中添加:
android:spinnerMode="dialog"
還有檢查 inflate 的 view 是不是 activity 的,不要搞到 application 上面去。
參考: https://blog.csdn.net/renjianhhong/article/details/49902837?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
https://blog.csdn.net/jamikabin/article/details/44831235
82. 輸入 ip 地址的 editText
android:inputType="text"
android:digits="0123456789."
Patterns.IP_ADDRESS.matcher("192.168.1.111").matches()
82. edittext 只顯示一行。
android:lines="1"
參考: https://blog.csdn.net/aidou1314/article/details/75116600
83. gson 解析錯誤
主要注意幾點:1. 數值前面不要有空格; 2. 類前面不要有空格。
錯誤如下:
"{\n" +
"\"resultcode\": 0," +
"\"person\": {" +
"}" +
"}";
上面的 0 前面有空格會解析錯誤, person 后面這個 { 前面有空格也會解析錯誤。
正確如下:
"{\n" +
"\"resultcode\":0," +
"\"person\":{" +
"}" +
"}";
84. 提示框。
是否提示框:
new AlertDialog.Builder(getActivity())
.setTitle("清空歷史數據")
.setMessage("是否確認")
.setPositiveButton("是", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
clear();
}
})
.setNegativeButton("否", null)
.show();
查找提示框:
final EditText editText = new EditText(getActivity());
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
editText.setLines(1);
new AlertDialog.Builder(getActivity())
.setTitle("查找歷史記錄")
.setMessage("請輸入身份證號: ")
.setView(editText)
.setPositiveButton("確定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
LinkedList<HistoryRecordItem> itemList = (LinkedList<HistoryRecordItem>) supertestApp.findHistoryRecordList(editText.getText().toString());
Map<Integer, Boolean> checkList = supertestApp.historyRecordItemListToCheckList(itemList);
supertestApp.getHistoryRecordAdapter().refreshList(itemList, checkList);
}
})
.setNegativeButton("取消", null)
.show();
參考: https://www.cnblogs.com/duoshou/articles/8622551.html
85. 自定義回調函數。
- 創建一個接口,接口里面是函數申明。
- 在模塊類里面,需要一個成員接口,然后需要一個設定接口的函數,把實現的接口函數賦值給成員接口,然后在需要處理的地方,調用接口里面的函數。
- 在主類里面,把具體的實現接口的函數賦值給模塊類里面的成員接口。
public interface UsbPlugSuccess {
void plugSuccess();
void plugRemove();
void plugError();
}
USBBrdcstReceiver
private UsbPlugSuccess usbPlugSuccess;
public void setPlugSuccess(UsbPlugSuccess usbPlugSuccess) {
this.usbPlugSuccess = usbPlugSuccess;
}
private void deviceInit(Context context, UsbMassStorageDevice device) {
try {
device.init();
Log.d(TAG, "readDevice init ok!");
Toast.makeText(context, "U盤插入,設備加載成功!", Toast.LENGTH_LONG).show();
hasPlugOk = true;
if (usbPlugSuccess != null) {
usbPlugSuccess.plugSuccess();
}
} catch (Exception e) {
Log.d(TAG, "device init failed: " + Log.getStackTraceString(e));
Toast.makeText(context, "U盤插入,設備加載失敗!", Toast.LENGTH_LONG).show();
hasPlugOk = false;
if (usbPlugSuccess != null) {
usbPlugSuccess.plugError();
}
}
}
ProjectManageFragment
supertestApp.getUsbBroadcastReceiver().setPlugSuccess(new UsbPlugSuccess() {
@Override
public void plugSuccess() {
checkImportButton(true);
}
@Override
public void plugRemove() {
checkImportButton(false);
}
@Override
public void plugError() {
checkImportButton(false);
}
});
參考: https://www.jianshu.com/p/7ac60e182449
https://www.cnblogs.com/yangjies145/p/7471849.html