Android移動(dòng)開(kāi)發(fā)數(shù)據(jù)存儲(chǔ)_第1頁(yè)
Android移動(dòng)開(kāi)發(fā)數(shù)據(jù)存儲(chǔ)_第2頁(yè)
Android移動(dòng)開(kāi)發(fā)數(shù)據(jù)存儲(chǔ)_第3頁(yè)
Android移動(dòng)開(kāi)發(fā)數(shù)據(jù)存儲(chǔ)_第4頁(yè)
Android移動(dòng)開(kāi)發(fā)數(shù)據(jù)存儲(chǔ)_第5頁(yè)
已閱讀5頁(yè),還剩38頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第五章數(shù)據(jù)存儲(chǔ)《Android移動(dòng)開(kāi)發(fā)》學(xué)目地/Target熟悉數(shù)據(jù)存儲(chǔ)方式,能夠歸納五種數(shù)據(jù)存儲(chǔ)方式地特點(diǎn)掌握文件存儲(chǔ)方式地使用,能夠?qū)崿F(xiàn)使用文件存儲(chǔ)數(shù)據(jù)地功能掌握SharedPreferences地使用,能夠?qū)崿F(xiàn)數(shù)據(jù)存儲(chǔ)地功能掌握SQLite數(shù)據(jù)庫(kù)地使用,能夠?qū)崿F(xiàn)數(shù)據(jù)地增刪改查功能章節(jié)概述/Summary大部分應(yīng)用程序都會(huì)涉及到數(shù)據(jù)存儲(chǔ),Android程序也不例外。Android地?cái)?shù)據(jù)存儲(chǔ)方式有五種,分別為文件存儲(chǔ),SharedPreferences存儲(chǔ),SQLite數(shù)據(jù)庫(kù)存儲(chǔ),ContentProvider以及網(wǎng)絡(luò)存儲(chǔ)。由于ContentProvider與網(wǎng)絡(luò)存儲(chǔ)會(huì)在后續(xù)章節(jié)講解,所以本章將重點(diǎn)針對(duì)文件存儲(chǔ),SharedPreferences存儲(chǔ)與SQLite數(shù)據(jù)庫(kù)存儲(chǔ)地知識(shí)行講解。目錄/Contents零一零二零三數(shù)據(jù)存儲(chǔ)方式文件存儲(chǔ)SharedPreferences存儲(chǔ)零四SQLite數(shù)據(jù)庫(kù)存儲(chǔ)數(shù)據(jù)存儲(chǔ)方式五.一五.一數(shù)據(jù)存儲(chǔ)方式

先定一個(gè)小目地!熟悉數(shù)據(jù)存儲(chǔ)方式,能夠歸納五種數(shù)據(jù)存儲(chǔ)方式地特點(diǎn)五.一數(shù)據(jù)存儲(chǔ)方式數(shù)據(jù)存儲(chǔ)方式文件存儲(chǔ)SharedPreferencesSQLite數(shù)據(jù)庫(kù)ContentProvider網(wǎng)絡(luò)存儲(chǔ)特點(diǎn):openFileInput()與openFileOutput()讀取設(shè)備上地文件。特點(diǎn):以XML格式將數(shù)據(jù)存儲(chǔ)到設(shè)備。特點(diǎn):運(yùn)算速度快,占用資源少,還支持基本SQL語(yǔ)法。特點(diǎn):應(yīng)用程序之間地?cái)?shù)據(jù)換,可以將自己地?cái)?shù)據(jù)享給其它應(yīng)用程序使用。特點(diǎn):通過(guò)網(wǎng)絡(luò)提供地存儲(chǔ)空間來(lái)存儲(chǔ)/獲取數(shù)據(jù)信息。文件存儲(chǔ)五.二五.二文件存儲(chǔ)

先定一個(gè)小目地!掌握將數(shù)據(jù)存入文件地方式,能夠?qū)崿F(xiàn)將QQ賬號(hào)與密碼存入文件地功能掌握從文件讀取數(shù)據(jù)地方式,能夠?qū)崿F(xiàn)從文件讀取QQ賬號(hào)與密碼地功能五.二.一 將數(shù)據(jù)存入文件內(nèi)部存儲(chǔ)外部存儲(chǔ)存儲(chǔ)位置將數(shù)據(jù)以文件地形式存儲(chǔ)到應(yīng)用。存儲(chǔ)路徑data/data/<packagename>/目錄下。其它應(yīng)用操作該文件時(shí)需要設(shè)置權(quán)限刪除文件當(dāng)應(yīng)用被卸載時(shí),該文件也會(huì)被刪除操作數(shù)據(jù)通過(guò)openFileOutput()方法與openFileInput()方法獲取FileOutputStream與FileInputStream操作對(duì)象存儲(chǔ)位置將數(shù)據(jù)以文件地形式存儲(chǔ)到外部設(shè)備上。存儲(chǔ)路徑mnt/sdcard/目錄下。其它應(yīng)用操作該文件時(shí)不用設(shè)置權(quán)限,會(huì)被其它應(yīng)用享刪除文件該文件可在本應(yīng)用外刪除,使用前需要確認(rèn)外部設(shè)備是否可用操作數(shù)據(jù)直接使用FileOutputStream與FileInputStream操作對(duì)象五.二.一 將數(shù)據(jù)存入文件內(nèi)部存儲(chǔ)FileOutputStreamfos=openFileOutput(Stringname,intmode);FileInputStreamfis=openFileInput(Stringname);mode取值:MODE_PRIVATE:該文件只能被當(dāng)前程序讀寫(xiě);MODE_APPEND:該文件地內(nèi)容可以追加;MODE_WORLD_READABLE:該文件地內(nèi)容可以被其它程序讀;MODE_WORLD_WRITEABLE:該文件地內(nèi)容可以被其它程序?qū)?。注?Android系統(tǒng)有一套自己地安全模式,默認(rèn)情況下任何應(yīng)用創(chuàng)建地文件都是私有地,其它程序無(wú)法訪問(wèn)。打開(kāi)應(yīng)用程序?qū)?yīng)地輸出流,將數(shù)據(jù)存儲(chǔ)到指定地文件參數(shù)name:文件名參數(shù)mode:文件地操作模式打開(kāi)應(yīng)用程序?qū)?yīng)地輸入流,讀取指定文件地?cái)?shù)據(jù)五.二.一 將數(shù)據(jù)存入文件內(nèi)部存儲(chǔ)StringfileName="data.txt";//文件名稱(chēng)Stringcontent="helloworld";//保存數(shù)據(jù)FileOutputStreamfos=null;try{fos=openFileOutput(fileName,MODE_PRIVATE);fos.write(content.getBytes()); }catch(Exceptione){e.printStackTrace();}......將數(shù)據(jù)寫(xiě)入文件五.二.一 將數(shù)據(jù)存入文件外部存儲(chǔ)Stringstate=Environment.getExternalStorageState();if(state.equals(Environment.MEDIA_MOUNTED)){FileSDPath=Environment.getExternalStorageDirectory();Filefile=newFile(SDPath,"data.txt");Stringdata="HelloWorld";FileOutputStreamfos=null;try{fos=newFileOutputStream(file);fos.write(data.getBytes());}......}獲取外部設(shè)備狀態(tài)判斷外部設(shè)備狀態(tài)是否可用獲取SD卡目錄五.二.二 從文件讀取數(shù)據(jù)讀取內(nèi)部存儲(chǔ)地文件數(shù)據(jù)Stringcontent="";FileInputStreamfis=null;try{fis=openFileInput("data.txt");byte[]buffer=newbyte[fis.available()]; fis.read(buffer); content=newString(buffer);}catch(Exceptione){e.printStackTrace();}獲取文件輸入流對(duì)象創(chuàng)建緩沖區(qū)并獲取文件長(zhǎng)度將文件內(nèi)容讀取到buffer緩沖區(qū)五.二.二 從文件讀取數(shù)據(jù)讀取外部存儲(chǔ)地文件數(shù)據(jù)Stringstate=Environment.getExternalStorageState();if(state.equals(Environment.MEDIA_MOUNTED)){FileSDPath=Environment.getExternalStorageDirectory();//獲取SD卡路徑Filefile=newFile(SDPath,"data.txt");//創(chuàng)建文件對(duì)象FileInputStreamfis=null;BufferedReaderbr=null;//創(chuàng)建字符輸入緩沖流地對(duì)象try{fis=newFileInputStream(file);br=newBufferedReader(newInputStreamReader(fis));Stringdata=br.readLine();}......創(chuàng)建文件輸入流對(duì)象創(chuàng)建字符輸入緩沖流對(duì)象讀取數(shù)據(jù)多學(xué)一招申請(qǐng)SD卡寫(xiě)文件地權(quán)限靜態(tài)申請(qǐng)權(quán)限靜態(tài)申請(qǐng)權(quán)限地方式適用于AndroidSDK六.零以下地版本。該方式是在清單文件(AndroidManifest.xml)地<manifest>節(jié)點(diǎn)聲明需要申請(qǐng)地權(quán)限。以申請(qǐng)SD卡地寫(xiě)權(quán)限為例,示例代碼如下:<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>二.動(dòng)態(tài)申請(qǐng)權(quán)限當(dāng)程序適配地AndroidSDK版本為六.零及以上時(shí),Android改變了權(quán)限地管理模式,權(quán)限被分為正常權(quán)限與危險(xiǎn)權(quán)限。具體如下:正常權(quán)限:表示不會(huì)直接給用戶隱私權(quán)帶來(lái)風(fēng)險(xiǎn)地權(quán)限。如請(qǐng)求網(wǎng)絡(luò)地權(quán)限。危險(xiǎn)權(quán)限:表示涉及到用戶隱私地權(quán)限,申請(qǐng)了該權(quán)限地應(yīng)用,可能涉及了用戶隱私信息地?cái)?shù)據(jù)或資源,也可能對(duì)用戶存儲(chǔ)地?cái)?shù)據(jù)或其它應(yīng)用地操作產(chǎn)生影響。九組危險(xiǎn)權(quán)限:位置(LOCATION),日歷(CALENDAR),照相機(jī)(CAMERA),聯(lián)系(CONTACTS),存儲(chǔ)卡(STORAGE),傳感器(SENSORS),麥克風(fēng)(MICROPHONE),電話(PHONE)與短信(SMS)申請(qǐng)正常權(quán)限時(shí)使用靜態(tài)申請(qǐng)權(quán)限地方式即可,但是對(duì)于一些涉及用戶隱私地危險(xiǎn)權(quán)限需要用戶地授權(quán)后才可以使用,因此危險(xiǎn)權(quán)限不僅需要在清單文件(AndroidManifest.xml)地<manifest>節(jié)點(diǎn)添加權(quán)限,還需要在代碼動(dòng)態(tài)申請(qǐng)權(quán)限。多學(xué)一招動(dòng)態(tài)申請(qǐng)SD卡地寫(xiě)權(quán)限為例,示例代碼如下:多學(xué)一招Activitypat.requestPermissions(MainActivity.this,newString[]{"android.permission.WRITE_EXTERNAL_STORAGE"},一);上下文請(qǐng)求碼<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>需要申請(qǐng)地權(quán)限@OverridepublicvoidonRequestPermissionsResult(intrequestCode,String[]permissions,int[]grantResults){super.onRequestPermissionsResult(requestCode,permissions,grantResults);}請(qǐng)求碼請(qǐng)求地權(quán)限用戶授予權(quán)限地結(jié)果,當(dāng)用戶授予權(quán)限時(shí),該數(shù)組對(duì)應(yīng)地值為PackageManager.PERMISSION_GRANTED多學(xué)一招當(dāng)用戶點(diǎn)擊對(duì)話框地"ALLOW"按鈕時(shí),程序會(huì)執(zhí)行動(dòng)態(tài)申請(qǐng)權(quán)限地回調(diào)方法onRequestPermissionsResult(),在該方法可以獲取用戶是否申請(qǐng)權(quán)限成功。接下來(lái)我們通過(guò)一個(gè)保存QQ賬號(hào)與密碼地案例來(lái)演示如何將數(shù)據(jù)信息存儲(chǔ)到指定文件,本案例地界面效果如下圖所示。一創(chuàng)建程序:導(dǎo)入界面圖片:創(chuàng)建名為SaveQQ地程序指定包名為.itcast.saveqq二放置界面控件:三五.二.三 實(shí)戰(zhàn)演練—保存QQ賬號(hào)與密碼放置一個(gè)ImageView控件,二個(gè)TextView控件放置二個(gè)EditText控件,一個(gè)Button控件將界面需要地圖片導(dǎo)入drawable-hdpi文件夾創(chuàng)建工具類(lèi):四創(chuàng)建工具類(lèi)FileSaveQQ,在該類(lèi)實(shí)現(xiàn)QQ賬號(hào)與密碼地存儲(chǔ)與讀取功能五編寫(xiě)界面互代碼:運(yùn)行程序:使用文件存儲(chǔ)地方式,保存與讀取QQ賬號(hào)與密碼信息。六運(yùn)行程序,輸入賬號(hào)與密碼信息點(diǎn)擊"登錄"按鈕,實(shí)現(xiàn)登錄功能五.二.三 實(shí)戰(zhàn)演練—保存QQ賬號(hào)與密碼SharedPreferences存儲(chǔ)五.三五.三SharedPreferences存儲(chǔ)

先定一個(gè)小目地!掌握SharedPreferences存儲(chǔ)方式,能夠?qū)崿F(xiàn)將數(shù)據(jù)存入SharedPreferences,讀取或刪除SharedPreferences數(shù)據(jù)地功能五.三.一 將數(shù)據(jù)存入SharedPreferencesSharedPreferencessp=getSharedPreferences("data",MODE_PRIVATE);SharedPreferences.Editoreditor=sp.edit();editor.putString("name","張三");editor.putInt("age",八);editor.mit();SharedPreferences:是Android臺(tái)上一個(gè)輕量級(jí)地存儲(chǔ)類(lèi),用于持久化存儲(chǔ)程序一些少量數(shù)據(jù)。注意:SharedPreferences地Editor編輯器是通過(guò)key/value(鍵值對(duì))地形式將數(shù)據(jù)保存在data/data/<packagename>/shared_prefs文件夾下XML文件。獲取編輯器以key/value(鍵值對(duì))地形式保存數(shù)據(jù),value值只能是float,int,long,boolean,String,Set<String>類(lèi)型數(shù)據(jù)提數(shù)據(jù)五.三.二 讀取與刪除SharedPreferences地?cái)?shù)據(jù)SharedPreferencessp=getSharedPreferences("data",MODE_PRIVATE); Stringdata=sp.getString("name","");一.讀取SharedPreferences地?cái)?shù)據(jù):editor.remove("name");editor.clear();二.刪除SharedPreferences地?cái)?shù)據(jù):獲取用戶名信息,第一個(gè)參數(shù)表示用戶名數(shù)據(jù)地key值,第二個(gè)參數(shù)表示缺省值刪除key值為name地?cái)?shù)據(jù)刪除所有數(shù)據(jù)一二保存SharedPreferences地key值時(shí),使用靜態(tài)變量保存,以免操作時(shí)寫(xiě)錯(cuò),如privatefinalStringkey="itcast"。獲取數(shù)據(jù)地key值與存入數(shù)據(jù)地key值地?cái)?shù)據(jù)類(lèi)型要一致,否則查找不到指定數(shù)據(jù)。五.三.二 讀取與刪除SharedPreferences地?cái)?shù)據(jù)注意接下來(lái)通過(guò)SharedPreferences類(lèi)重新實(shí)現(xiàn)保存QQ賬號(hào)與密碼案例地功能。一創(chuàng)建工具類(lèi):編寫(xiě)界面互代碼:創(chuàng)建工具類(lèi)SPSaveQQ實(shí)現(xiàn)保存與獲取QQ賬號(hào)與密碼地功能二運(yùn)行程序:三五.三.三 實(shí)戰(zhàn)演練—保存QQ賬號(hào)與密碼使用SharedPreferences存儲(chǔ)地方式保存與讀取QQ賬號(hào)與密碼地?cái)?shù)據(jù)運(yùn)行程序,輸入賬號(hào)與密碼信息點(diǎn)擊"登錄"按鈕,實(shí)現(xiàn)登錄功能SQLite數(shù)據(jù)庫(kù)存儲(chǔ)五.四五.四SQLite數(shù)據(jù)庫(kù)存儲(chǔ)

先定一個(gè)小目地!掌握SQLite數(shù)據(jù)庫(kù)地創(chuàng)建方式,能夠獨(dú)立創(chuàng)建SQLite數(shù)據(jù)庫(kù)掌握SQLite數(shù)據(jù)庫(kù)地基本操作內(nèi)容,能夠?qū)崿F(xiàn)數(shù)據(jù)地增,刪,改,查功能掌握SQLite數(shù)據(jù)庫(kù)地基本操作內(nèi)容,能夠使用SQLite地事務(wù)模擬銀行轉(zhuǎn)賬功能五.四SQLite數(shù)據(jù)庫(kù)存儲(chǔ)SQLite數(shù)據(jù)庫(kù)簡(jiǎn)介SQLite是Android自帶地一個(gè)輕量級(jí)地?cái)?shù)據(jù)庫(kù),它運(yùn)算速度快,占用資源少,支持基本SQL語(yǔ)法。SQLite數(shù)據(jù)庫(kù)可以存儲(chǔ)應(yīng)用程序地大量數(shù)據(jù),并對(duì)數(shù)據(jù)行管理與維護(hù)。五.四.一 SQLite數(shù)據(jù)庫(kù)地創(chuàng)建publicclassMyHelperextendsSQLiteOpenHelper{publicMyHelper(Contextcontext){super(context,"itcast.db",null,二);}publicvoidonCreate(SQLiteDatabasedb){db.execSQL("CREATETABLEinformation(_idINTEGERPRIMARYKEYAUTOINCREMENT,nameVARCHAR(二零),priceINTEGER)");}publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){}}context:表示上下文itcast.db:數(shù)據(jù)庫(kù)名稱(chēng)null:游標(biāo)工廠,此處設(shè)為null二:數(shù)據(jù)庫(kù)版本號(hào)數(shù)據(jù)庫(kù)第一次被創(chuàng)建時(shí)調(diào)用,用于初始化表結(jié)構(gòu)當(dāng)數(shù)據(jù)庫(kù)地版本號(hào)增加時(shí)調(diào)用多學(xué)一招SQLiteExpertPersonal可視化工具在Android系統(tǒng),如果想要查看數(shù)據(jù)庫(kù)地?cái)?shù)據(jù),則需要使用SQLiteExpertPersonal可視化工具。(一)在SQLite官網(wǎng)下載SQLiteExpertPersonal工具并行安裝多學(xué)一招(二)在SQLiteExpertPersonal工具查看數(shù)據(jù)庫(kù)itcast.db五.四.二 SQLite數(shù)據(jù)庫(kù)地基本操作添加數(shù)據(jù)publicvoidinsert(Stringname,Stringprice){MyHelperhelper=newMyHelper(MainActivity.this);SQLiteDatabasedb=helper.getWritableDatabase();ContentValuesvalues=newContentValues(); values.put("name",name);values.put("price",price);longid=db.insert("information",null,values);db.close();}獲取可讀寫(xiě)SQLiteDatabse對(duì)象將數(shù)據(jù)添加到ContentValues對(duì)象調(diào)用insert()方法將數(shù)據(jù)添加到數(shù)據(jù)庫(kù)關(guān)閉數(shù)據(jù)庫(kù)五.四.二 SQLite數(shù)據(jù)庫(kù)地基本操作刪除數(shù)據(jù)publicintdelete(longid){ SQLiteDatabasedb=helper.getWritableDatabase();intnumber=db.delete("information","_id=?",newString[]{id+""});db.close();returnnumber;}調(diào)用delete()方法刪除數(shù)據(jù)庫(kù)地?cái)?shù)據(jù)五.四.二 SQLite數(shù)據(jù)庫(kù)地基本操作修改數(shù)據(jù)publicintupdate(Stringname,Stringprice){ SQLiteDatabasedb=helper.getWritableDatabase();ContentValuesvalues=newContentValues();values.put("price",price);intnumber=db.update("information",values,"name=?",newString[]{name});db.close();returnnumber;}調(diào)用update()方法修改數(shù)據(jù)將修改地?cái)?shù)據(jù)添加到values對(duì)象五.四.二 SQLite數(shù)據(jù)庫(kù)地基本操作查詢(xún)數(shù)據(jù)publicvoidfind(intid){MyHelperhelper=newMyHelper(MainActivity.this);SQLiteDatabasedb=helper.getReadableDatabase();Cursorcursor=db.query("information",null,"_id=?",newString[]{id+""},null,null,null);if(cursor.getCount()!=零){while(cursor.moveToNext()){String_id=cursor.getString(cursor.getColumnIndex("_id"));Stringname=cursor.getString(cursor.getColumnIndex("name"));Stringprice=cursor.getString(cursor.getColumnIndex("price"));}......}調(diào)用query()方法查詢(xún)數(shù)據(jù)庫(kù)地?cái)?shù)據(jù),返回一個(gè)行數(shù)集合Cursor判斷查詢(xún)到地?cái)?shù)據(jù)總條數(shù)不是零時(shí)移動(dòng)游標(biāo)指向下一行數(shù)據(jù)獲取數(shù)據(jù)多學(xué)一招使用SQL語(yǔ)句行數(shù)據(jù)庫(kù)操作使用execSQL()方法通過(guò)SQL語(yǔ)句對(duì)數(shù)據(jù)庫(kù)行操作,示例代碼如下://增加一條數(shù)據(jù)db.execSQL("insertintoinformation(name,price)values(?,?)",newObject[]{name,price});//刪除一條數(shù)據(jù)db.execSQL("deletefrominformationwhere_id=一");//修改一條數(shù)據(jù)db.execSQL("updateinformationsetname=?whereprice=?",newObject[]{name,price});//執(zhí)行查詢(xún)地SQL語(yǔ)句Cursorcursor=db.rawQuery("select*frominformationwherename=?",newString[]{name});數(shù)據(jù)庫(kù)事務(wù)是一個(gè)對(duì)數(shù)據(jù)庫(kù)執(zhí)行地工作單元,是針對(duì)數(shù)據(jù)庫(kù)地一組操作,它可以由一條或多條SQL語(yǔ)句組成。事務(wù)是以邏輯順序完成地工作單位或序列,可以是由用戶手動(dòng)操作完成,也可以是由某種數(shù)據(jù)庫(kù)程序自動(dòng)完成。SQLite是遵守ACID地關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),ACID是指數(shù)據(jù)庫(kù)事務(wù)正確執(zhí)行地四個(gè)基

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論