Android學習筆記(二)

來源:互聯網
上載者:User

Handler的使用

       1.Handler類是android.os下的一個類,handler.post(Runnable r)可以將一個線程添加到訊息佇列中;handler.postDelay(Runnable r, long delayTime)在延遲delayTime毫秒後,將線程添加到訊息佇列中;handler.removeCalbacks(Runnable r)將隊列中掛起的Runnable移出。

       2.Handler.obtainMessage()可以獲得一條訊息,這個訊息有兩個整型的參數arg1和arg2,利用它可以傳遞訊息。在建立Handler的時候,如果用

  Handler handler = new Handler(){

         @Override

         public void handleMessage(Message msg){

                ……

         }

  }

  來建立的話,該handler可以從訊息佇列(MessageQueue)中取出訊息並在handleMessage方法中處理。而在另一個地方,也可以使用handler.sendMessage(Message msg)來向訊息佇列中發送訊息。

  Handler對於線程的處理並不是另外開啟一個線程,而是在原有線程的基礎上調用另一個Runnable的run函數。HanlderThread類實現了Looper來處理訊息佇列的功能,這個類由Android作業系統提供。利用該類,可以使用getLooper()(在使用getLooper()方法之前,必須調用該類的start()方法,否則這個Looper是null)方法來擷取這個Looper,之後,將這個Looper以參數的形式傳遞給Handler的建構函式,此時這個Handler的handleMessage()方法就可以由另一個線程來處理了,就不會阻塞Activity。

       可以把Bundle看作一個特殊的Map,只是它的鍵固定為String類型,值也只有幾種基本的資料類型。

       在使用Message傳遞資料的時候,發送之前可以使用Message.obj來傳遞一個資料,這個資料是一個Object即可。處理訊息的時候,也可以使用Message.obj來擷取,此時需要向下轉型。如果需要傳遞大量資料,可以使用Message.setData(Bundle data)。

       Message.sendToTarget();方法可以講這個message發送給建立這個Message的Handler,在這個Handler裡面可以接收該Message。

SQLite的使用

       1. SQLiteOpenHelper類的使用

    public abstract class SQLiteOpenHelper類中有幾個函數:

    onCreate(SQLiteDatabase db);當資料庫第一次建立的時候調用這個方法

    onOpen(SQLiteDatabase db);當資料庫被開啟的時候調用這個方法

    onUpgrade(SQLiteDatabase db);當資料庫需要升級的時候調用這個方法

    getReadableDatabase();獲得可以讀的資料庫

    getWritbaleDatabase();獲得可以寫的資料庫

       我們一般繼承這個類,然後調用建構函式(父類沒有預設建構函式)。資料庫的版本為整數,從1開始,每次升級資料庫版本的時候,這個值依次遞增。當發現這個值變化的時候,就意味著資料庫已經進行了版本升級。

       使用SQLiteDatabase.execSQL(String sql)來執行SQL語句。

       2.adb工具的使用

可以使用adb工具(在cmd中輸入adb即可,在這之前需要為它配置環境變數,在sdk/platform-tools下面,另一個就是要保證模擬器AVD是開啟的,否則會報錯)來查看資料庫中的變化:

       adb shell:進入Linux命令列(android作業系統是以Linux為核心的)

       ls –l:以完整的形式顯示檔案和檔案夾

       cd data:進入data

       cd data:再進入data

       這裡面有很多檔案夾(以應用程式的包名命名),每一個應用程式都有一個檔案夾

       cd com.example.sqlite3:進入我們當前的應用程式

       建立資料庫後,這裡面會多一個叫databases的檔案夾

       cd databases:進入這個檔案夾,這裡面可以看到剛剛建立的資料庫

       sqlite3 mydb:使用SQLite開啟資料庫mydb

       然後就可以像Mysql一樣使用資料庫了:

       select * from table_name;……

       3.插入資料

       使用ContentValues類來協助插入資料:

  ContentValues values = new ContentValues();

  values.put(“id”,1);//第一個參數為列名,第二個參數為列的值

  values.put(“name”,”alvis”);

  //DatabaseHelper類繼承於SQLiteOpenHelper類

  DatabaseHelper dbHelper = new DatabaseHelper(MainActivity.this,”mydb”);

  //得到一個資料庫物件

  SQLiteDatabase db = dbHelper.getWritableDatabase();

  db.insert(“user”,null,values);//調用insert方法插入資料。

  insert方法的第一個參數為表名,第二個直接填null即可。第三個為帶有資料的ContentValues對象。

  4.更新資料

  DatabaseHelper dbHelper = new DatabaseHelper(MainActivity.this,”mydb”);

  //得到一個資料庫物件

  SQLiteDatabase db = dbHelper.getWritableDatabase();

  ContentValues values = new ContentValues();

  values.put(“name”,”alvis”);

  db.update(“user”,values,”id=?”,new String[]{“1”});//這裡使用預留位置來設定參數

  整個這幾句其實就組成了一句話:

  update user set name=’alvis’ where id=1;

  update方法第一個參數是要更新的表名,第二個參數是帶有要更新值的ContentValues對象,第三個參數是where字句的條件(可以有多個),第四個參數為where字句的值,類型為String[]。

       5.查詢資料

              DatabaseHelper dbHelper = new DatabaseHelper(MainActivity.this,”mydb”);

              SQLiteDatabase db = dbHelper.getWritableDatabase();

              Cursor cursor = db.query(“user”, new String[]{“id”,”name”}, ”id=?”, new String[]{“1”},null,null,”id” );

              while(cursor.moveToNext()){

                     //這裡處理獲得的資料

                     String result = cursor.getString(cursor.getColumnIndex(“name”));

                     System.out.println(result);

              }

       cursor.moveToNext()方法有兩個作用: 將遊標下移看是否有下一條記錄,有就返回true,否則返回false,就是說把指標移到下一個位置的同時還判斷是否還有值。

       query方法的參數依次為(後面三個參數均為字串):

表名,查詢的欄位,查詢條件,條件的參數,groupBy,having,orderBy

其實就是把一條select語句分解成了很多部分。

       使用cursor擷取資料的時候,參數一定要是要查詢所在列的索引,這個索引可以通過cursor.getColumn(String columnName)來獲得,於是就有了上面的寫法。

       建議不要太多的依賴於資料庫,也不要在SQLite資料庫中存入太多的資料,因為在開發的時候可能會出現很多奇怪的問題。

Android程式調試

       可以使用Log類來輸出調試資訊:

       Log.i(String tag,String message);//Info層級的

       Log.v(String tag,String message);//致命的

       Log.w(String tag,String message);//警告

       Log.e(String tag,String message);//錯誤

       Log.d(String tag,String message);//調試

檔案下載

  1.下載檔案的步驟:

  1).建立一個URL對象

  URL url = new URL(String urlStr);

  2).建立一個HttpURLConnection

  HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();

  3).獲得一個InputStream對象

  InputStream inputStream = urlConn.getInputStream();

  然後就可以使用流操作讀取這個inputStream了

  4).訪問網路的許可權:在Manifest.xml中聲明:

  <uses-permission android:name="android.permission.INTERNET"/>

       原始碼:

       class DownloadMP3Listener implements OnClickListener{

              @Override

              public void onClick(View v) {

                     HttpDownloader httpDownloader = new HttpDownloader();

                     int status = httpDownloader.downFile("http://192.168.2.104:8080/source/ yiwangeshebude.mp3", "Download", "一萬個捨不得.mp3");

              }

       }

       錯誤:android.os.NetworkOnMainThreadException

  這個異常大概意思是在主線程訪問網路時出的異常。 Android在4.0之前的版本 支援在主線程中訪問網路,但是在4.0以後對這部分程式進行了最佳化,也就是說訪問網路的代碼不能寫在主線程中了。

  解決辦法:重新開啟一個線程去跑網路相關的代碼。

  class DownloadMP3Listener implements OnClickListener{

              @Override

              public void onClick(View v) {

                     new Thread(){      //重新開啟一個線程去訪問網路

                            @Override

                            public void run(){

                                   HttpDownloader httpDownloader = new HttpDownloader();

                          int status = httpDownloader.downFile("http://192.168.2.104:8080/source/ yiwangeshebude.mp3", "Download", "一萬個捨不得.mp3");

                            }

}.start();

                }

         }

       2.訪問SD卡

       1).得到當前裝置SD卡的目錄:一般就是 /SDCARD

              String path = Environment.getExternalStorageDirectory();

       2).在Manifest.xml檔案中設定訪問SD卡的許可權(和application標籤同級)

              <uses-permission android:name="android.permission.INTERNET"/>

ContentProvider初步

       1.每一個ContentProvider都有一個公用的URI,這個URI表示這個ContentProvider所提供的資料。Android提供的ContentProvider都在android.provider包中。

       2.ContentProvider所提供的函數:

       query():查詢             insert():插入                    update():更新

   delete():刪除            getType():得到資料類型  onCreate():建立時的回呼函數

  3.實現ContentProvider的過程:

       1).定義一個CONTENT_URI常量

       2).定義一個類,繼承ContentProvider類

       3).實現query,insert,update,delete,getType和onCreate方法

       4).在AndroidManifest.xml中進行聲明

XML檔案解析

       ContentHandler介面

       ContentHandler是Java類包中一個特殊的SAX介面,位於org.xml.sax包中,該介面封裝了一些對事件處理的方法,當XML解析器開始解析XML輸入文檔時,它會遇到某些特殊的事件,比如文檔的開頭和結束、元素的開頭和結束、以及元素中的字元資料等事件。當遇到這些事件時,XML解析器會調用ContentHandler介面中相應的方法來響應該事件。

       ContentHandler介面的方法有以下幾種:

       void startDocument()

       void endDocument()

       void startElement(String uri,String localName,String qName,Attributes atts)

       void endElement(String uri,String localName,String qName)

       void characters(char[] ch,int start,int length)讀取到中間的字元的時候調用

       通常的處理流程如下:

       1).建立事件處理常式

       2).建立SAX解析器

       3).將事件處理常式分配給解析器

       4).對文檔進行解析,將每個時間發送給處理常式

       如下面的例子:

   //1.建立一個SAXParserFactory

       SAXParserFactory factory = SAXParserFactory.newInstance();

       //2.通過這個factory獲得一個XMLReader

       XMLReader reader = factory.newSAXParser().getXMLReader();

       //3.為XMLReader設定內容處理器

       //注意這個方法的參數是一個ContentHander,但是由於ContentHandler裡面的

       //方法太多,因此這裡使用適配器模式,MyContentHandler是繼承於DefaultHandler

   //的,而DefaultHandler實現了ContentHanlder介面。

       reader.setContentHandler(new MyContentHandler());

       //4.開始解析檔案

       reader.parse(new InputSource(new StringReader(xml)));

廣播機制

       如果要監聽某一類事件,則需要在Manifest.xml檔案中聲明:

       <receiver android:name=”.TestReceiver”>

              <inteng-filter>

                     <action androi:name=”andriod.intent.action.EDIT”/>

              </intent-filter>

       </receiver>

  同時接收方需要繼承BroadcastReceiver類,並複寫onReceiver方法:

       class TestReceiver extends BroadcastReceiver{

    @Override

    public void onReceiver(Context context, Intent intent){

                       //這裡寫處理流程

    }

       }

       注意藍色部分的匹配。

       而在發送方,可以使用:

       Intent intent = new Intent();

       intent.setAction(Intent.ACTION_EDIT);

       TestActivity.this.sendBrodcast(intent);

       注意紅色的部分需要匹配,否則接收不到這個訊息。

       這個程式的大體流程是:TestActivity廣播了一個action為ACTION_EDIT的 intent,TestReceiver因為繼承了BroadcastReceiver,因此是一個廣播的接收器,但是至於接不接收由TestActivity廣播的intent,就要看在Manifest.xml檔案中對TestReceiver的配置了。

在Manifest.xml檔案中對於TestReceiver的配置裡,<intent-filter>的<action>標籤指明了TestReceiver監聽的哪種action,只有當TestActivity廣播的intent中的action和這裡的action相同的時候,才會接收到,此時會產生一個TestReceiver,並調用該類的onReceiver方法。

       注意:TestReceiver只做一次處理,如果處理過了,那麼這個對象就沒用了,如果再有同樣的廣播發送出來,那麼作業系統會再產生這樣一個對象來處理。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.