當前位置:首頁 » 安卓系統 » onupgradeandroid

onupgradeandroid

發布時間: 2022-07-08 06:22:34

1. android 怎麼讀取資料庫中的數據

android讀取資料庫可以使用sqlite一些api進行讀取,實例如下:

java">/**
*查找一條數據
*@paramuid
*/
publicUserfind(Integeruid){
SQLiteDatabasedb=dbOpenHelper.getReadableDatabase();//創建資料庫輔助類
Cursorcursor=db.rawQuery("select*fromuserwhereuid=?",newString[]{uid.toString()});//創建一個游標
if(cursor.moveToFirst()){//循環遍歷查找數組
intuid2=cursor.getInt(cursor.getColumnIndex("uid"));
Stringuname=cursor.getString(cursor.getColumnIndex("uname"));
Stringuaddress=cursor.getString(cursor.getColumnIndex("uaddress"));
Useruser=newUser();
user.setUid(uid2);
user.setUname(uname);
user.setUaddress(uaddress);
returnuser;
}
cursor.close();
returnnull;
}

2. 求幫助,android實例化資料庫問題

在上一個例子中,我們對Android系統自帶的SQLite資料庫進行了初步的學習,了解了一些增、刪、改、查的基本工作。在這一節的例子當中,我們做了一個非常簡便的日記本程序,雖然沒有完善,但是已經是基本可以使用了。在例子當中,我們不但要對資料庫進行增、刪、改、查的操作,而且還要把資料庫當中的數據顯示在一個ListView當中,通過對ListView的操作,實現對數據的增、刪、改、查操作。

通過這個例子我們可以學到以下操作:

如何對DatabaseHelper和SQLiteDatabase封裝,以便讓我們訪問資料庫更加方便和安全;

如何利用ContentValues類來代替原始的SQL語句進行資料庫的操作;

如何使用SimpleCursorAdapter類和ListView配合進行ListView的顯示。

日記本具體實現步驟如下所述。

1.第一步

在Eclipse中打開ex08_2_SQLite 項目,具體操作步驟如下。

新建一個項目。單擊File→New→Android Project項。

在新建項目的對話框中,選擇Create project from existing source項。

單擊瀏覽,找到ex08_2_SQLite項目,然後單擊確定。

程序的目錄結構如圖8-16所示。

2.第二步

我們首先運行一下建立的程序,將會出現如圖8-17所示。

(點擊查看大圖)圖8-16 程序的目錄結構

(點擊查看大圖)圖8-17 沒有任何數據的程序主界面

程序的主Activity是ActivityMain,它是一個ListActivity,和它關聯的布局文件是diary_list.xml。關於ListActivity的介紹。請參閱第7章關於ListView的介紹。

3.第三步

在繼續操作前,讓我們重點關注一下DiaryDbAdapter類,這個類封裝了DatabaseHelper和SQLiteDatabase類,使得我們對資料庫的操作更加安全和方便。

在DiaryDbAdapter的類變數里,主要定義了以下幾個變數:

資料庫、數據表、數據表中列的名字;

DatabaseHelper 和SQLiteDatabase的實例;

Context 實例。

DatabaseHelper 類的定義和上一個例子一樣,只不過這個例子里邊,我們在onUpgrade增加了升級的代碼,具體如下所示:

private static class DatabaseHelper extends SQLiteOpenHelper {

DatabaseHelper(Context context) {

super(context, DATABASE_NAME, null, DATABASE_VERSION);

}

@Override

public void onCreate(SQLiteDatabase db) {

//生成資料庫

db.execSQL(DATABASE_CREATE);

@Override

public void onUpgrade(SQLiteDatabase db,
int oldVersion, int newVersion) {

db.execSQL("DROP TABLE IF EXISTS diary");

onCreate(db);
}
}
代碼解釋:

在DiaryDbAdapter類里,向外界提供了以下一些方法。

open(),調用這個方法後,如果資料庫還沒有建立,那麼會建立資料庫,如果資料庫已經建立了,那麼會返回可寫的資料庫實例。

close(),調用此方法,DatabaseHelper 會關閉對資料庫的訪問。

createDiary(String title, String body)通過一個title和body欄位在資料庫當中創建一條新的紀錄。

deleteDiary(long rowId)通過記錄的id,刪除資料庫中的那條記錄。

getAllNotes()得到diary表中所有的記錄,並且以一個Cursor的形式進行返回。

getDiary(long rowId)通過記錄的主鍵id,得到特定的一條記錄。

updateDiary(long rowId, String title, String body)更新主鍵id為rowId那條記錄中的兩個欄位title和body欄位的內容。

小知識 什麼是ContentValues類?

ContentValues類和Hashtable比較類似,它也是負責存儲一些名值對,但是它存儲的名值對當中的名是一個String類型,而值都是基本類型。

我們回顧一下,在上一個例子當中,我們是通過SQL語句進行插入操作,SQL語句的好處是比較直觀,但是容易出錯。但是在這個例子當中我們有更好的辦法,在這里我們將要插入的值都放到一個ContentValues的實例當中,然後執行插入操作,具體代碼如下所示:

public long createDiary(String title, String body) {

ContentValues initialValues = new ContentValues();

initialValues.put(KEY_TITLE, title);
initialValues.put(KEY_BODY, body);
Calendar calendar = Calendar.getInstance();

// 生成年月日字元串

String created = calendar.get(Calendar.YEAR)
+"年"+calendar.get(Calendar. MONTH)+"月"+calendar.get
(Calendar.DAY_OF_MONTH)+"日"+calendar.get(Calendar.
HOUR_OF _DAY)+"時"+calendar.get(Calendar.MINUTE)+"分";

initialValues.put(KEY_CREATED, created);

return mDb.insert(DATABASE_TABLE, null, initialValues);

}
代碼解釋:

ContentValues initialValues = new ContentValues()語句實例化一個contentValues類。

initialValues.put(KEY_TITLE, title)語句將列名和對應的列值放置到initialValues里邊。

mDb.insert(DATABASE_TABLE, null, initialValues)語句負責插入一條新的紀錄,如果插入成功則會返回這條記錄的id,如果插入失敗會返回-1。

在更新一條記錄的時候,我們也是採用ContentValues 的這套機制,具體代碼如下所示:

public boolean updateDiary(long rowId, String title, String body) {

ContentValues args = new ContentValues();

args.put(KEY_TITLE, title);
args.put(KEY_BODY, body);
Calendar calendar = Calendar.getInstance();

String created = calendar.get(Calendar.YEAR) + "年"

+ calendar.get(Calendar.MONTH) + "月"

+ calendar.get(Calendar.DAY_OF_MONTH) + "日"

+ calendar.get(Calendar.HOUR_OF_DAY) + "時"

+ calendar.get(Calendar.MINUTE) + "分";

args.put(KEY_CREATED, created);

return mDb.update(DATABASE_TABLE, args,
KEY_ROWID + "=" + rowId, null) > 0;

}
代碼解釋:

實現更新一條記錄。

4.第四步

現在返回到程序的主界面,對應的Activity是ActivityMain。

當我們單擊menu按鈕後會出現如圖8-18所示界面。

根據我們第7章對menu的學習,對單擊menu里邊按鈕的處理邏輯全部放在onMenuItem Selected函數里,具體代碼如下所示:

public boolean onMenuItemSelected(int featureId, MenuItem item) {

switch (item.getItemId()) {

case INSERT_ID:

createDiary();

return true;

case DELETE_ID:

mDbHelper.deleteDiary(getListView().getSelectedItemId());
renderListView();

return true;

}

return super.onMenuItemSelected(featureId, item);

}
代碼解釋:

如果單擊添加一篇新日記按鈕那麼會執行到createDiary()語句。

如果單擊刪除一條記錄,會執行mDbHelper.deleteDiary(getListView().getSelectedItemId())語句,首先刪除當前被選中的某一項所對應的資料庫當中的記錄。

renderListView()語句重新對界面刷新。

在createDiary()函數里邊的代碼如下所示:

private void createDiary() {

Intent i = new Intent(this, ActivityDiaryEdit.class);

startActivityForResult(i, ACTIVITY_CREATE);
}
代碼解釋:

首先構造了一個intent,這個intent負責跳轉到ActivityDiaryEdit里。

然後啟動這個intent,並且需要返回值。

5.第五步

在ActivityMain中,有多處地方都用到了renderListView()函數。在onCreate里邊用這個函數顯示ListView。當ListView需要發生變化後,例如,刪除了一條記錄或者增加了一條記錄的時候,我們調用這個函數進行刷新ListView,下邊來看一下此函數的實現,具體代碼如下所示:

private void renderListView() {
mDiaryCursor = mDbHelper.getAllNotes();
startManagingCursor(mDiaryCursor);

String[] from = new String[] { DiaryDbAdapter.KEY_TITLE,

DiaryDbAdapter.KEY_CREATED };

int[] to = new int[] { R.id.text1, R.id.created };

SimpleCursorAdapter notes = new SimpleCursorAdapter(this,

R.layout.diary_row, mDiaryCursor, from, to);
setListAdapter(notes);
}
代碼解釋:

mDiaryCursor = mDbHelper.getAllNotes()語句,我們首先獲取資料庫當中的所有數據,這些數據以Cursor的形式存在。

startManagingCursor(mDiaryCursor)語句,我們將生成的Cursor交給Activity來管理,這樣的好處是系統能自動做很多事情,比如當程序暫停的時候,這個系統可以卸載Cursor以節省空間,當程序重新啟動的時候系統重新查詢生成Cursor。

String[] from 里邊定義了ListView每一排對應的數據是從資料庫中的哪個列表裡選取。

和SimpleAdapter類似 int[] to 里邊是一個View的數組。這些View只能是TextView或者ImageView。這些View是以id的形式來表示的,如Android.R.id.text1。

SimpleCursorAdapter notes = new SimpleCursorAdapter(this,R.layout.diary_row, mDiaryCursor, from, to)語句生成一個SimpleCursorAdapter ,我們介紹以下每一個參數的意義。

第一個參數是Context。

第二個參數為R.layout.diary_row,它關聯在diary_row.xml文件當中定義的Layout,這個Layout規定ListView當中每一項的布局。

第三個參數就是Cursor。

第四個參數是數據表當中的列的數組,只有在這里邊出現的列名,數據才會對應的填充在to里邊對應的TextView或者ImageView當中。

第五個參數是在ListView里邊每一項中需要被數據填充的TextView或者ImageView。

setListAdapter(notes)語句將SimpleCursorAdapter 和ListActivity里邊的ListView綁定起來,至此在界面當中才會顯示出列表來。

小知識 什麼是SimpleCursorAdapter ?

在第7章,我們已經介紹過了ArrayAdapter和SimpleAdapter。和它們倆類似,SimpleCursorAdapter 也是集成Adapter。ArrayAdapter負責把一個字元串數組中的數據填充到一個ListView當中,而對應的SimpleCursorAdapter 負責把Cursor里邊的內容填充到ListView當中。通過SimpleCursorAdapter 可以把資料庫當中一列的數據和ListView中一排進行對應起來。和前兩個Adapter類似,要求和數據進行對應的View必須是TextView或者ImageView。

6.第六步

單擊添加一條數據的按鈕,程序運行界面如圖8-19所示。

這個界面對應的Activity是ActivityDiaryEdit,對應的布局文件是diary_edit.xml。對於這個布局文件里邊用到了LinearLayout、TextView和EditText,這些我們都已經講過,在這里不再贅述,具體看一下代碼:

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"

Android:orientation="vertical" Android:layout_width="fill_parent"

Android:layout_height="fill_parent">

<LinearLayout Android:orientation="vertical"

Android:layout_width="fill_parent"

Android:layout_height="wrap_content">

<TextView Android:layout_width="wrap_content"

Android:layout_height="wrap_content" Android:text="@string/title"

Android:padding="2px" />

<EditText Android:id="@+id/title"

Android:layout_width="fill_parent"

Android:layout_height="wrap_content" Android:layout_weight="1" />

</LinearLayout>

<TextView Android:layout_width="wrap_content"

Android:layout_height="wrap_content" Android:text="@string/body" />

<EditText Android:id="@+id/body" Android:layout_width="fill_parent"

Android:layout_height="wrap_content" Android:layout_weight="1"

Android:scrollbars="vertical" />

<Button Android:id="@+id/confirm" Android:text="@string/confirm"

Android:layout_width="wrap_content"

Android:layout_height="wrap_content" />

</LinearLayout>
代碼解釋:

在一個LinearLayout里邊我們放置了一些文本框、輸入框和一些Button按鈕。

當程序運行輸入內容後,單擊確定按鈕,日記就會保存到資料庫當中。下邊來看一下代碼具體是怎麼執行的。當單擊確定按鈕後,系統回調執行和按鈕綁定的單擊監聽器里邊的onClick方法,具體代碼如下所示:

public void onClick(View view) {
String title = mTitleText.getText().toString();
String body = mBodyText.getText().toString();

if (mRowId != null) {

mDbHelper.updateDiary(mRowId, title, body);

} else

mDbHelper.createDiary(title, body);

Intent mIntent = new Intent();

setResult(RESULT_OK, mIntent);
finish();
}
代碼解釋:

首先獲得EditView里邊的數據。

目前mRowId 為null,所以執行mDbHelper.createDiary(title, body)語句將數據保存到數據當中。

setResult(RESULT_OK, mIntent)語句設置返回值。

執行完上邊的代碼後,系統跳轉到ActivityMain,並執行回調函數onActivityResult,具體代碼如下所示:

protected void onActivityResult(int requestCode, int resultCode,
Intent intent) {

super.onActivityResult(requestCode, resultCode, intent);

renderListView();
}
代碼解釋:

在回調函數中,我們重新對ListView進行刷新,將所有的數據重新顯示出。

7.第七步

單擊ListView里邊的條列,可以對剛才保存的數據進行編輯。具體怎麼實現這個功能的,我們可以看一下ActivityMain當中的onListItemClick方法代碼:

protected void onListItemClick(ListView l,
View v, int position, long id) {

super.onListItemClick(l, v, position, id);

Cursor c = mDiaryCursor;
c.moveToPosition(position);

Intent i = new Intent(this, ActivityDiaryEdit.class);

i.putExtra(DiaryDbAdapter.KEY_ROWID, id);
i.putExtra(DiaryDbAdapter.KEY_TITLE, c.getString
(c .getColumnIndexOrThrow(DiaryDbAdapter.KEY_TITLE)));
i.putExtra(DiaryDbAdapter.KEY_BODY, c.getString
(c .getColumnIndexOrThrow(DiaryDbAdapter.KEY_BODY)));
startActivityForResult(i, ACTIVITY_EDIT);
}
代碼解釋:

c.moveToPosition(position)語句將在Cursor當中的指針移到position位置,這個position是我們單擊的這個一列在整個列表中的位置。

Intent i = new Intent(this, ActivityDiaryEdit.class)語句構造一個跳轉到ActivityDiaryEdit的intent。

putExtra()方法負責將要傳遞的數據放到intent當中。

c.getString(c.getColumnIndexOrThrow(DiaryDbAdapter.KEY_TITLE))得到這一條數據中列名為title的值。

c.getString(c.getColumnIndexOrThrow(DiaryDbAdapter.KEY_BODY))得到這一條數據中列名為body的值。

startActivityForResult(i, ACTIVITY_EDIT)語句啟動intent,發生Activity的跳轉。

我們來看一下ActivityDiaryEdit中的onCreate()里邊的代碼:

Bundle extras = getIntent().getExtras();

if (extras != null) {

String title = extras.getString(DiaryDbAdapter.KEY_TITLE);
String body = extras.getString(DiaryDbAdapter.KEY_BODY);
mRowId = extras.getLong(DiaryDbAdapter.KEY_ROWID);

if (title != null) {

mTitleText.setText(title);
}

if (body != null) {

mBodyText.setText(body);
}
}
代碼解釋:

對於ActivityDiaryEdit這個Activity有兩個intent可以跳轉進來,一個是新建一篇日記的時候,這個時候intent里邊的extras部分沒有任何數據。第二種情況是在單擊列表的某一個條列的時候,這個時候的intent如上所示會攜帶extras數據。所以在ActivityDiaryEdit中我們通過判斷extras是否為null,就可以判斷是哪種intent啟動的。

當extras不為null,我們將extras里邊的數據顯示出來。

8.第八步

在程序的主界面當中,上下移動焦點(可以通過鍵盤的上下鍵或者模擬器中的上下按鍵),可以對擁有焦點的那一項進行刪除,如圖8-20、圖8-21、圖8-22所示。

(點擊查看大圖)圖8-20 上下移動焦點界面
具體執行onMenuItemSelected中的代碼:

mDbHelper.deleteDiary(getListView().getSelectedItemId());
renderListView();
代碼解釋:

getListView()方法獲取當前的ListView引用。

getSelectedItemId()方法得到當前這一列所對應的數據項的rowId,也就是這條數據在資料庫中的主鍵id。

(點擊查看大圖)圖8-21 進行刪除界面

(點擊查看大圖)圖8-22 刪除後界面

mDbHelper.deleteDiary()方法刪去資料庫中的這一列數據。

renderListView()負責對列表重新刷新一遍。

至此,對資料庫的學習就先告一段落,接下來將學習contentProvider,它是Android應用當中非常重要的一部分。而且程序間的大部分數據交換都是通過contentProvider機制進行。

3. android中在onupgrade可以執行插入數據操作嗎

當然正常情況下,我們都會傳入一個資料庫文件名的,所以這個方法一般不會執行的,那麼就走下面的代碼。下面的代碼就是直接打開一個資料庫。不過我們看到一個特點,就是創建資料庫和Context有關系呢。我們看一下Context中的代碼。不過這里我們知道Context是一個抽象類,我們一般會看他的子類ContextImpl實現:
主要看一下getDatabasePath方法和openOrCreateDatabase方法:
首先來看一下openOrCreateDatabase方法:

[java] view plain
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory,
DatabaseErrorHandler errorHandler) {
File f = validateFilePath(name, true);
int flags = SQLiteDatabase.CREATE_IF_NECESSARY;
if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {
flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;
}
SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler);
setFilePermissionsFromMode(f.getPath(), mode, 0);
return db;
}
這里我們看到其實還是調用了SQLiteDatabase的openDatabase方法

4. android 資料庫升級會清空以前存的數據嗎

Android應用程序更新的時候如果資料庫修改了欄位需要更新資料庫,並且保留原來的資料庫數據:
這是原有的資料庫表
CREATE_BOOK = "create table book(bookId integer primarykey,bookName text);";
然後我們增加一個欄位:
CREATE_BOOK = "create table book(bookId integer primarykey,bookName text,bookContent text);";
首先我們需要把原來的資料庫表重命名一下
CREATE_TEMP_BOOK = "alter table book rename to _temp_book";
然後把備份表中的數據到新創建的資料庫表中
INSERT_DATA = "insert into book select *,' ' from _temp_book";(注意' '是為新加的欄位插入默認值的必須加上,否則就會出錯)。
然後我們把備份表幹掉就行啦。
DROP_BOOK = "drop table _temp_book";
然後把資料庫的版本後修改一下,再次創建資料庫操作對象的時候就會自動更新(註:更新的時候第一個創建的操作數據的對象必須是可寫的,也就是通過這個方法getWritableDatabase()獲取的資料庫操作對象)
然後在onUpgrade()方法中執行上述sql語句就OK了
public class DBservice extends SQLiteOpenHelper{
private String CREATE_BOOK = "create table book(bookId integer primarykey,bookName text);";
private String CREATE_TEMP_BOOK = "alter table book rename to _temp_book";
private String INSERT_DATA = "insert into book select *,'' from _temp_book";
private String DROP_BOOK = "drop table _temp_book";
public DBservice(Context context, String name, CursorFactory factory,int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CREATE_BOOK);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
switch (newVersion) {
case 2:
db.execSQL(CREATE_TEMP_BOOK);
db.execSQL(CREATE_BOOK);
db.execSQL(INSERT_DATA);
db.execSQL(DROP_BOOK);
break;
}
}

5. android 版本更新後資料庫會清空嗎

這個不會的,Android版本的更新會把之前的數據保存起來的。

6. Android 資料庫如何更新

1、設置一個DB_VERSION

publicstaticfinalintDB_VERSION=1;

2、當你要更新表的時候就把DB_VERSION+1,就會觸發onUpgrade,資料庫就更新了,記得採納

publicDBHelper(){
//fortest
Config=newDbManager.DaoConfig()
.setDbName(DB_NAME)
.setDbVersion(DB_VERSION)
.setDbDir(Environment.getExternalStorageDirectory())
.setDbOpenListener(newDbManager.DbOpenListener(){
@Override
publicvoidonDbOpened(DbManagerdb){
db.getDatabase().enableWriteAheadLogging();
}
})
.setDbUpgradeListener(newDbManager.DbUpgradeListener(){
@Override
publicvoidonUpgrade(DbManagerdb,intoldVersion,intnewVersion){
updateTable(db,xx.class);

}
});
}

7. 將開發的android app 安裝到手機上後,如何在如見代碼中替換手機上原有的資料庫

android sqlite資料庫,第一次調用getWritableDatabase或者getReadableDatabase後,就會在程序的包下創建一個資料庫,之前執行SQLiteOpenHelper的onCreate方法,
當資料庫創建了以後,是不會再創建的,只有通過升級資料庫版本號來實現
當資料庫的版本號發生了變化以後,SQLiteOpenHelper會調用onUpgrade方法
因此都是在onUpgrade來處理新增欄位,新增表等操作

要替換資料庫
將原來資料庫放到res/raw目錄下,程序啟動的時候,通過流讀取了來,並寫到你程序目錄下
String dbfile = "/data"+ Environment.getDataDirectory().getAbsolutePath() + "/"+ context.getPackageName()+"資料庫名"
InputStream is = context.getResources().openRawResource(R.raw.data);

FileOutputStream fos = new FileOutputStream(dbfile);
byte[] buffer = new byte[1024];
int count = 0;
while ((count =is.read(buffer)) > 0) {
fos.write(buffer, 0, count);
fos.flush();
}
fos.close();
is.close();
這樣就把資料庫給替換了,但是通常不建議這么做
最好是在onUpgrade來處理

請採納哈

8. Android中復寫SQLiteOpenHelper的onUpgrade()方法為什麼不寫代碼

因為資料庫結構沒跟隨資料庫版本迭代

9. android SQLiteDatabase中的update函數用法是什麼

1·創建資料庫Android
不自動提供資料庫。在
Android
應用程序中使用
SQLite,必須自己創建資料庫,然後創建表、索引,填充數據。Android
提供了
SQLiteOpenHelper
幫助你創建一個資料庫,你只要繼承
SQLiteOpenHelper
類,就可以輕松的創建資料庫。
2·SQLiteOpenHelper
類根據開發應用程序的需要,封裝了創建和更新資料庫使用的邏輯。SQLiteOpenHelper
的子類,至少需要實現三個方法:構造函數,調用父類
SQLiteOpenHelper
的構造函數。
3·這個方法需要四個參數:
上下文環境(例如,一個
Activity),
資料庫名字,
一個可選的游標工廠(通常是
Null),
一個代表你正在使用的資料庫模型版本的整數。onCreate()方法,它需要一個
SQLiteDatabase
對象作為參數,根據需要對這個對象填充表和初始化數據。onUpgrage()
方法,它需要三個參數,一個
SQLiteDatabase
對象,一個舊的版本號和一個新的版本號,這樣你就可以清楚如何把一個資料庫從舊的模型轉變到新的模型。
public
class
DatabaseHelper
extends
SQLiteOpenHelper
{
DatabaseHelper(Context
context,
String
name,
CursorFactory
cursorFactory,
int
version)
{
super(context,
name,
cursorFactory,
version);
}
@Override
public
void
onCreate(SQLiteDatabase
db)
{
//
TODO
創建資料庫後,對資料庫的操作
}
@Override
public
void
onUpgrade(SQLiteDatabase
db,
int
oldVersion,
int
newVersion)
{
//
TODO
更改資料庫版本的操作
}

super.onOpen(db);

//
TODO
每次成功打開資料庫後首先被執行
}
}
復制代碼接下來討論具體如何創建表、插入數據、刪除表等等。

熱點內容
scratch少兒編程課程 發布:2025-04-16 17:11:44 瀏覽:619
榮耀x10從哪裡設置密碼 發布:2025-04-16 17:11:43 瀏覽:347
java從入門到精通視頻 發布:2025-04-16 17:11:43 瀏覽:62
php微信介面教程 發布:2025-04-16 17:07:30 瀏覽:288
android實現陰影 發布:2025-04-16 16:50:08 瀏覽:781
粉筆直播課緩存 發布:2025-04-16 16:31:21 瀏覽:334
機頂盒都有什麼配置 發布:2025-04-16 16:24:37 瀏覽:197
編寫手游反編譯都需要學習什麼 發布:2025-04-16 16:19:36 瀏覽:791
proteus編譯文件位置 發布:2025-04-16 16:18:44 瀏覽:350
土壓縮的本質 發布:2025-04-16 16:13:21 瀏覽:578