當前位置:首頁 » 安卓系統 » android線程與線程通信方式

android線程與線程通信方式

發布時間: 2022-06-30 10:53:02

A. android線程間通信有哪些方式

進程:是具有一定獨立功能的程序關於某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。
  線程:是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程自己基本上不擁有系統資源,只擁有一些在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。
  區別:
  (1)、一個程序至少有一個進程,一個進程至少有一個線程;
  (2)、線程的劃分尺度小於進程,使得多線程程序的並發性高;
  (3)、進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉。
---------------------
一、Android進程間通信方式
1.Bundle
  由於Activity,Service,Receiver都是可以通過Intent來攜帶Bundle傳輸數據的,所以我們可以在一個進程中通過Intent將攜帶數據的Bundle發送到另一個進程的組件。
  缺點:無法傳輸Bundle不支持的數據類型。
2.ContentProvider
  ContentProvider是Android四大組件之一,以表格的方式來儲存數據,提供給外界,即Content Provider可以跨進程訪問其他應用程序中的數據。用法是繼承ContentProvider,實現onCreate,query,update,insert,delete和getType方法,onCreate是負責創建時做一些初始化的工作,增刪查改的方法就是對數據的查詢和修改,getType是返回一個String,表示Uri請求的類型。注冊完後就可以使用ContentResolver去請求指定的Uri。
3.文件
  兩個進程可以到同一個文件去交換數據,我們不僅可以保存文本文件,還可以將對象持久化到文件,從另一個文件恢復。要注意的是,當並發讀/寫時可能會出現並發的問題。
4.Broadcast
  Broadcast可以向android系統中所有應用程序發送廣播,而需要跨進程通訊的應用程序可以監聽這些廣播。
5.AIDL方式
  Service和Content Provider類似,也可以訪問其他應用程序中的數據,Content Provider返回的是Cursor對象,而Service返回的是java對象,這種可以跨進程通訊的服務叫AIDL服務。
AIDL通過定義服務端暴露的介面,以提供給客戶端來調用,AIDL使伺服器可以並行處理,而Messenger封裝了AIDL之後只能串列運行,所以Messenger一般用作消息傳遞。
6.Messenger
  Messenger是基於AIDL實現的,服務端(被動方)提供一個Service來處理客戶端(主動方)連接,維護一個Handler來創建Messenger,在onBind時返回Messenger的binder。
  雙方用Messenger來發送數據,用Handler來處理數據。Messenger處理數據依靠Handler,所以是串列的,也就是說,Handler接到多個message時,就要排隊依次處理。
7.Socket
  Socket方法是通過網路來進行數據交換,注意的是要在子線程請求,不然會堵塞主線程。客戶端和服務端建立連接之後即可不斷傳輸數據,比較適合實時的數據傳輸
二、Android線程間通信方式
  一般說線程間通信主要是指主線程(也叫UI線程)和子線程之間的通信,主要有以下兩種方式:
1.AsyncTask機制
  AsyncTask,非同步任務,也就是說在UI線程運行的時候,可以在後台的執行一些非同步的操作;AsyncTask可以很容易且正確地使用UI線程,AsyncTask允許進行後台操作,並在不顯示使用工作線程或Handler機制的情況下,將結果反饋給UI線程。但是AsyncTask只能用於短時間的操作(最多幾秒就應該結束的操作),如果需要長時間運行在後台,就不適合使用AsyncTask了,只能去使用Java提供的其他API來實現。
2.Handler機制
  Handler,繼承自Object類,用來發送和處理Message對象或Runnable對象;Handler在創建時會與當前所在的線程的Looper對象相關聯(如果當前線程的Looper為空或不存在,則會拋出異常,此時需要在線程中主動調用Looper.prepare()來創建一個Looper對象)。使用Handler的主要作用就是在後面的過程中發送和處理Message對象和讓其他的線程完成某一個動作(如在工作線程中通過Handler對象發送一個Message對象,讓UI線程進行UI的更新,然後UI線程就會在MessageQueue中得到這個Message對象(取出Message對象是由其相關聯的Looper對象完成的),並作出相應的響應)。
三、Android兩個子線程之間通信
  面試的過程中,有些面試官可能會問Android子線程之間的通信方式,由於絕大部分程序員主要關注的是Android主線程和子線程之間的通信,所以這個問題很容易讓人懵逼。
  主線程和子線程之間的通信可以通過主線程中的handler把子線程中的message發給主線程中的looper,或者,主線程中的handler通過post向looper中發送一個runnable。但looper默認存在於main線程中,子線程中沒有Looper,該怎麼辦呢?其實原理很簡單,把looper綁定到子線程中,並且創建一個handler。在另一個線程中通過這個handler發送消息,就可以實現子線程之間的通信了。
  子線程創建handler的兩種方式:
  方式一:給子線程創建Looper對象:
new Thread(new Runnable() {
public void run() {
Looper.prepare(); // 給這個Thread創建Looper對象,一個Thead只有一個Looper對象
Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
Looper.loop(); // 不斷遍歷MessageQueue中是否有消息
};
}).start();
---------------------
方式二:獲取主線程的looper,或者說是UI線程的looper:
new Thread(new Runnable() {
public void run() {
Handler handler = new Handler(Looper.getMainLooper()){ // 區別在這!!!
@Override
public void handleMessage(Message msg) {
Toast.makeText(getApplicationContext(), "handleMessage", Toast.LENGTH_LONG).show();
}
};
handler.sendEmptyMessage(1);
};
}).start();

B. Android 線程間通信有哪幾種方式

Android 的廣播機制 在 Android 裡面有各種各樣的廣播,比如電池的使用狀態,電話的接收和簡訊的接收都會產生一個廣播,應用程序開發者也可以監聽這些廣播並做出程序邏輯的處理。下面我畫一張粗略的圖來幫助大家理解廣播的運行機制。 Android 中有各式各樣的廣播,各種廣播在Android 系統中運行,當系統/應用程序運行時便會向 Android 注冊各種廣播,Android 接收到廣播會便會判斷哪種廣播需要哪種事件,然後向不同需要事件的應用程序注冊事件,不同的廣播可能處理不同的事件也可能處理相同的廣播事件,這時就需要 Android 系統為我們做篩選。 案例分析: 一個經典的電話黑名單,首先通過將黑名單號碼保存在資料庫裡面,當來電時,我們接收到來電廣播並將黑名單號碼與資料庫中的某個數據做匹配,如果匹配的話則做出相應的處理,比如掛掉電話、比如靜音等等。。。 Demo 分析: 下面通過一個小DEMO 來講解一下廣播在Android 中如何編寫,在Demo中我們設置了一個按鈕為按鈕設置點擊監聽通過點擊發送廣播,在後台中接收到廣播並列印LOG信息。代碼如下: BroadCastActivity 頁面代碼 public class BroadCastActivity extends Activity { public static final String ACTION_INTENT_TEST = "com.terry.broadcast.test"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button btn = (Button) findViewById(R.id.Button01); btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub Intent intent = new Intent(ACTION_INTENT_TEST); sendBroadcast(intent); } }); } } 接收器代碼如下: public class myBroadCast extends BroadcastReceiver { public myBroadCast() { Log.v("BROADCAST_TAG", "myBroadCast"); } @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub Log.v("BROADCAST_TAG", "onReceive"); } } Android 廣播的生命周期 在上面的接收器中,繼承了BroadcastReceiver 並重寫了它的onReceive 並構造了一個函數,下面通過圖片來一步一步認識 Android 廣播的生命周期。當我點擊一下按鈕,它向Android 發送了一個廣播,如下圖: 這時我們再點擊一下按鈕,它還是會再向 Android 系統發送廣播,此時日誌信息如下: 下面本人畫一張圖像,描述了Android 中廣播的生命周期,其次它並不像Activity 一樣復雜,運行原理很簡單如下圖: 下面來看一下SDK給出的解釋: 大意為:如果一個廣播處理完onReceive 那麼系統將認定此對象將不再是一個活動的對象,也就會finished掉它。 至此,大家應該能明白 Android 的廣播生命周期的原理,代碼也不用多介紹,很簡單的一個發送廣播並處理廣播的Demo。 Android 如何判斷並篩選廣播? 前 面說過 Android 的廣播有各式各樣,那麼Android 系統是如何幫我們處理我們需要哪種廣播並為我們提供相應的廣播服務呢?這里有一點需要大家注意,每實現一個廣播接收類必須在我們應用程序中的 manifest 中顯式的註明哪一個類需要廣播,並為其設置過濾器,如下圖: Tip:action 代表一個要執行的動作,在Andriod 中有很action 比如 ACTION_VIEW,ACTION_EDIT 那麼有些人會問了,如果我在一個廣播接收器中要處理多個動作呢?那要如何去處理? 在Android 的接收器中onReceive 以經為我們想到的,同樣的你必須在Intent-filter 裡面注冊該動作,可以是系統的廣播動作也可以是自己需要的廣播,之後你之需要在onReceive 方法中,通過intent.getAction()判斷傳進來的動作即可做出不同的處理,不同的動作。具體大家可以去嘗試測試一下。 小結: 在Android 中如果要發送一個廣播必須使用sendBroadCast 向系統發送對其感興趣的廣播接收器中。 使用廣播必須要有一個intent 對象必設置其action動作對象 使用廣播必須在配置文件中顯式的指明該廣播對象 每次接收廣播都會重新生成一個接收廣播的對象 在BroadCast 中盡量不要處理太多邏輯問題,建議復雜的邏輯交給Activity 或者 Service 去處理 Android廣播機制(兩種注冊方法) 在android下,要想接受廣播信息,那麼這個廣播接收器就得我們自己來實現了,我們可以繼承BroadcastReceiver,就可以有一個廣播接受器了。有個接受器還不夠,我們還得重寫BroadcastReceiver裡面的onReceiver方法,當來廣播的時候我們要干什麼,這就要我們自己來實現,不過我們可以搞一個信息防火牆。具體的代碼: public class SmsBroadCastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); Object[] object = (Object[])bundle.get("ps"); SmsMessage sms[]=new SmsMessage[object.length]; for(int i=0;i { sms[0] = SmsMessage.createFromP((byte[])object[i]); Toast.makeText(context, "來自"+sms[i].getDisplayOriginatingAddress()+" 的消息是:"+sms[i].getDisplayMessageBody(), Toast.LENGTH_SHORT).show(); } //終止廣播,在這里我們可以稍微處理,根據用戶輸入的號碼可以實現簡訊防火牆。 abortBroadcast(); } } 當實現了廣播接收器,還要設置廣播接收器接收廣播信息的類型,這里是信息:android.provider.Telephony.SMS_RECEIVED 我們就可以把廣播接收器注冊到系統裡面,可以讓系統知道我們有個廣播接收器。這里有兩種,一種是代碼動態注冊: //生成廣播處理 smsBroadCastReceiver = new SmsBroadCastReceiver(); //實例化過濾器並設置要過濾的廣播 IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED"); //注冊廣播 BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver, intentFilter); 一種是在AndroidManifest.xml中配置廣播 package="spl.broadCastReceiver" android:versionCode="1" android:versionName="1.0"> android:label="@string/app_name"> 兩種注冊類型的區別是: 1)第一種不是常駐型廣播,也就是說廣播跟隨程序的生命周期。 2)第二種是常駐型,也就是說當應用程序關閉後,如果有信息廣播來,程序也會被系統調用自動運行。 BroadcastReceiver用於監聽被廣播的事件 必須被注冊,有兩種方法: 1、在應用程序的代碼中注冊 注冊BroadcastReceiver: registerReceiver(receiver,filter); 取消注冊BroadcastReceiver: unregisterReceiver(receiver); 當BroadcastReceiver更新UI,通常會使用這樣的方法注冊。啟動Activity時候注冊BroadcastReceiver,Activity不可見時候,取消注冊。 2、在androidmanifest.xml當中注冊 使用這樣的方法注冊弊端:它會始終處於活動狀態,畢竟是手機開發,cpu和電源資源比較少,一直處於活動耗費大,不利。

C. 面試被問到android中兩個子線程怎麼通信,我懵了。

構造HandlerThread類的對象mHandlerThread,這樣生成一個子線程可以調用new MyHandler(mHandlerThread.getLooper())來獲取子線程的handler,另一個子線程發消息,收到消息的就是子線程而不是主線程了。

D. android線程及handler的關系

handler是android特有的機制,最大的好處就是實現了Activity主線程(就是UI主線程)和其他線程(自己定義的Thread)之間的數據通信。Timer和Thread是實現多線程的,而handler是實現線程間通信的,二者很大不同,關於handler的用法

E. Android 進程間通信的幾種實現方式

Android 進程間通信的幾種實現方式

主要有4種方式:

這4種方式正好對應於android系統中4種應用程序組件:Activity、Content Provider、Broadcast和Service。

主要實現原理:

由於應用程序之間不能共享內存。為了在不同應用程序之間交互數據(跨進程通訊),AndroidSDK中提供了4種用於跨進程通訊的方式進行交互數據,實現進程間通信主要是使用sdk中提供的4組組件根據實際開發情況進行實現數據交互。

詳細實現方式:

Acitivity實現方式

Activity的跨進程訪問與進程內訪問略有不同。雖然它們都需要Intent對象,但跨進程訪問並不需要指定Context對象和Activity的 Class對象,而需要指定的是要訪問的Activity所對應的Action(一個字元串)。有些Activity還需要指定一個Uri(通過 Intent構造方法的第2個參數指定)。 在android系統中有很多應用程序提供了可以跨進程訪問的Activity,例如,下面的代碼可以直接調用撥打電話的Activity。

IntentcallIntent=newIntent(Intent.ACTION_CALL,Uri.parse("tel:12345678");
startActivity(callIntent);


Content Provider實現方式

Android應用程序可以使用文件或SqlLite資料庫來存儲數據。Content Provider提供了一種在多個應用程序之間數據共享的方式(跨進程共享數據)

應用程序可以利用Content Provider完成下面的工作

1. 查詢數據
2. 修改數據
3. 添加數據
4. 刪除數據

Broadcast 廣播實現方式

廣播是一種被動跨進程通訊的方式。當某個程序向系統發送廣播時,其他的應用程序只能被動地接收廣播數據。這就象電台進行廣播一樣,聽眾只能被動地收聽,而不能主動與電台進行溝通。在應用程序中發送廣播比較簡單。只需要調用sendBroadcast方法即可。該方法需要一個Intent對象。通過Intent對象可以發送需要廣播的數據。


Service實現方式

常用的使用方式之一:利用AIDL Service實現跨進程通信

這是我個人比較推崇的方式,因為它相比Broadcast而言,雖然實現上稍微麻煩了一點,但是它的優勢就是不會像廣播那樣在手機中的廣播較多時會有明顯的時延,甚至有廣播發送不成功的情況出現。

注意普通的Service並不能實現跨進程操作,實際上普通的Service和它所在的應用處於同一個進程中,而且它也不會專門開一條新的線程,因此如果在普通的Service中實現在耗時的任務,需要新開線程。

要實現跨進程通信,需要藉助AIDL(Android Interface Definition Language)。Android中的跨進程服務其實是採用C/S的架構,因而AIDL的目的就是實現通信介面。


總結

跨進程通訊這個方面service方式的通訊遠遠復雜於其他幾種通訊方式,實際開發中Activity、Content Provider、Broadcast和Service。4種經常用到,學習過程中要對沒種實現方式有一定的了解。

F. Android中進程與進程、線程與線程之間如何通信

線程之間有消息循環的話,一般採用Message Handler機制; 進程間一般採用AIDL方式進行通信。

G. 在android中進程間通信機制是怎樣的

一般都是基於ARM處理器的吧 安卓的內核也是基於Linux的吧。 網路實現依靠TCP/IP協議棧實現實行封包和解包以及連接的建立和控制,還涉及到你手機的硬體網卡等。 進程間通信方式一般採用的消息隊列,共享內存,套接字,還有管道了。 多線程是由操作系統來管理每個線程的CPU時間和資源的分配。也是比較復雜的,涉及到線程間通信,線程同步等。 內存管理是由操作系統進行分段,分頁。分配機制比較復雜的,涉及到碎片的減少,內存的回收等。 要想了解詳細內容,可以看看Linux操作系統原理。或者google提供的相關文檔。

H. Android中線程與線程,進程與進程之間如何通信

使用handler發送message,消息隊列排隊

進程是一個具有獨立功能的程序關於某個數據集合的一次運行活動。它可以申請和擁有系統資源,是一個動態的概念,是一個活動的實體。它不只是程序的代碼,還包括當前的活動,通過程序計數器的值和處理寄存器的內容來表示。
進程是一個「執行中的程序」。程序是一個沒有生命的實體,只有處理器賦予程序生命時,它才能成為一個活動的實體,我們稱其為進程。
通常在一個進程中可以包含若干個線程,它們可以利用進程所擁有的資源。在引入線程的操作系統中,通常都是把進程作為分配資源的基本單位,而把線程作為獨立運行和獨立調度的基本單位。由於線程比進程更小,基本上不擁有系統資源,故對它的調度所付出的開銷就會小得多,能更高效的提高系統內多個程序間並發執行的程度。
線程和進程的區別在於,子進程和父進程有不同的代碼和數據空間,而多個線程則共享數據空間,每個線程有自己的執行堆棧和程序計數器為其執行上下文。多線程主要是為了節約CPU時間,發揮利用,根據具體情況而定。線程的運行中需要使用計算機的內存資源和CPU。

I. android開發中跨進程通信有幾種方式

Android進程間通信的幾種方式 定義多進程
第一:Android應用中使用多進程只有一個辦法(用NDK的fork來做除外),就是在AndroidManifest.xml中聲明組件時,用android:process屬性來指定。
不知定process屬性,則默認運行在主進程中,主進程名字為包名。
android:process = package:remote,將運行在package:remote進程中,屬於全局進程,其他具有相同shareUID與簽名的APP可以跑在這個進程中。
android:process = :remote ,將運行在默認包名:remote進程中,而且是APP的私有進程,不允許其他APP的組件來訪問。
第二:多進程引發的問題
靜態成員和單例失效:每個進程保持各自的靜態成員和單例,相互獨立。
線程同步機制失效:每個進程有自己的線程鎖。
SharedPreferences可靠性下降:不支持並發寫,會出現臟數據。
Application多次創建:不同進程跑在不同虛擬機,每個虛擬機啟動會創建自己的Application,自定義Application時生命周期會混亂。
綜上,不同進程擁有各自獨立的虛擬機,Application,內存空間,由此引發一系列問題。
第三: 進程間通信
Bundle/Intent傳遞數據:
可傳遞基本類型,String,實現了Serializable或Parcellable介面的數據結構。Serializable是Java的序列化方法,Parcellable是Android的序列化方法,前者代碼量少(僅一句),但I/O開銷較大,一般用於輸出到磁碟或網卡;後者實現代碼多,效率高,一般用戶內存間序列化和反序列化傳輸。
文件共享:
對同一個文件先後寫讀,從而實現傳輸,Linux機制下,可以對文件並發寫,所以要注意同步。順便一提,Windows下不支持並發讀或寫。
Messenger:
Messenger是基於AIDL實現的,服務端(被動方)提供一個Service來處理客戶端(主動方)連接,維護一個Handler來創建Messenger,在onBind時返回Messenger的binder。
雙方用Messenger來發送數據,用Handler來處理數據。Messenger處理數據依靠Handler,所以是串列的,也就是說,Handler接到多個message時,就要排隊依次處理。
AIDL:
AIDL通過定義服務端暴露的介面,以提供給客戶端來調用,AIDL使伺服器可以並行處理,而Messenger封裝了AIDL之後只能串列運行,所以Messenger一般用作消息傳遞。
通過編寫aidl文件來設計想要暴露的介面,編譯後會自動生成響應的java文件,伺服器將介面的具體實現寫在Stub中,用iBinder對象傳遞給客戶端,客戶端bindService的時候,用asInterface的形式將iBinder還原成介面,再調用其中的方法。
ContentProvider:
系統四大組件之一,底層也是Binder實現,主要用來為其他APP提供數據,可以說天生就是為進程通信而生的。自己實現一個ContentProvider需要實現6個方法,其中onCreate是主線程中回調的,其他方法是運行在Binder之中的。自定義的ContentProvider注冊時要提供authorities屬性,應用需要訪問的時候將屬性包裝成Uri.parse("content://authorities")。還可以設置permission,readPermission,writePermission來設置許可權。 ContentProvider有query,delete,insert等方法,看起來貌似是一個資料庫管理類,但其實可以用文件,內存數據等等一切來充當數據源,query返回的是一個Cursor,可以自定義繼承AbstractCursor的類來實現。
Socket:
學過計算機網路的對Socket不陌生,所以不需要詳細講述。只需要注意,Android不允許在主線程中請求網路,而且請求網路必須要注意聲明相應的permission。然後,在伺服器中定義ServerSocket來監聽埠,客戶端使用Socket來請求埠,連通後就可以進行通信。

J. 大神救命啊 android線程間通信 handler message之類的

線程間通訊(三種方式)::
public class AnrActivity extends Activity implements OnClickListener {
TextView text;
Handler handler;
ProgressBar bar;

private class MyAsycnTask extends AsyncTask<URL, Integer, String>{

@Override
protected void onProgressUpdate(Integer... values) {

bar.setProgress(values[0]);
text.setText("進度:"+values[0]+"%");
super.onProgressUpdate(values);
}
@Override
protected String doInBackground(URL... params) {
for (int i = 0; i <100; i++) {
try {
publishProgress(i+1);
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "success";
}
@Override
protected void onPostExecute(String result) {
text.setText(result);
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Button down = (Button) this.findViewById(R.id.button1);
Button receiver = (Button) this.findViewById(R.id.button2);
Button update = (Button)this.findViewById(R.id.button3);
bar = (ProgressBar)this.findViewById(R.id.progressBar1);
text = (TextView)this.findViewById(R.id.text);

update.setOnClickListener(this);
down.setOnClickListener(this);
receiver.setOnClickListener(this);

}

@Override
public void onClick(final View v) {

switch (v.getId()) {
case R.id.button1:
//通過 Asycntask 進行通訊
MyAsycnTask myAsycnTask = new MyAsycnTask();
myAsycnTask.execute(null);
break;

case R.id.button2:
//通過發送通知進行通訊
Intent intent = new Intent();
intent.putExtra("test", "receiver");
intent.setAction("com.tarena.test");
sendBroadcast(intent);//發送通知
break;

case R.id.button3:
// 通過 new Thread()或者runOnUiThread()或者Handler 實現
new Thread(){
public void run() {
CommontUtils.timeConsuming(2);
Runnable action = new Runnable() {

@Override
public void run() {
Toast.makeText(AnrActivity.this, "update_success", 0).show();
text.setText("update_success");

}
};
//runOnUiThread(action);
//handler.post(action);
v.post(action);

}

}.start();
break;

熱點內容
mc中國版伺服器地址 發布:2024-04-20 15:33:13 瀏覽:411
手機修改wifi密碼網站是什麼 發布:2024-04-20 15:22:05 瀏覽:322
js源碼下載 發布:2024-04-20 15:05:16 瀏覽:20
編譯翻譯的區別 發布:2024-04-20 14:55:53 瀏覽:894
登錄之後qq密碼要在哪裡看 發布:2024-04-20 14:55:03 瀏覽:730
天龍多開腳本 發布:2024-04-20 14:53:05 瀏覽:771
同一段代碼編譯的長度不同 發布:2024-04-20 14:24:14 瀏覽:380
緩存美劇權力的游戲 發布:2024-04-20 14:16:52 瀏覽:988
如何刪除word文件保存密碼 發布:2024-04-20 14:15:18 瀏覽:824
紅米安卓10如何降級到安卓9 發布:2024-04-20 14:13:25 瀏覽:31