Android基礎3

來源:互聯網
上載者:User

標籤:android   des   style   blog   http   color   

 

 

一、內容觀察者的運行原理

運行過程通常為A應用對內容提供者暴露的資料進行修改,而B應用負則專門責監聽內容提供者資料的變化。

1、簡單的小示範

首先在內容提供者寫一個MyContentProvider類繼承ContentProvider如下

public class MyContentProvider extends ContentProvider

繼承後會自動重寫6個方法(增刪改查onCreat和getBytes)在B應用對應修改的方法(增刪改)中發出通知,getContext().getContentResolver().notifyChange(uri, null);

通知A應用(觀察者內容發生變化),A應用的

Uri uri=Uri.parse("content://qjq");

getContentResolver().query(uri, null, null, null, null);

Log.i(TAG, "查詢已完成");

//監聽資料的改變。參數二notifyForDescendents boolean  是否級聯   

getContentResolver().registerContentObserver(uri, true, new MyContentObserver(new Handler()));

Log.i(TAG, "已經設定了監聽");}

private class MyContentObserver extends ContentObserver{}//重寫建構函式和onChange方法

 

二、使用內容觀察者監聽簡訊資料的改變(掌握)

簡訊的資料存放的位置,

 

源碼的資訊清單檔裡面

 

簡訊的存放的位置

核心的URI

 

代碼:

 

二、簡訊監聽器

getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, new MyContentObserver(new Handler()));MyContentObserver為自己new的一個類繼承ContentObserver重寫onChange方法代碼如下

public void onChange(boolean selfChange) {

// TODO Auto-generated method stub

super.onChange(selfChange);

//如果簡訊內容改變  方法會被系統自動調用

//擷取最新的那條簡訊  (查詢簡訊資料   需要許可權  讀簡訊的許可權)

//address 號碼  ,body 內容 

Cursor c = getContentResolver().query(Uri.parse("content://sms"), new String[]{"address","body"}, null, null, "_id desc");

c.moveToFirst();

String address=c.getString(0);

String body=c.getString(1);

Log.i(TAG, "address:"+address+",body:"+body);

c.close();     }

三、ANR異常(即使用者點擊按鈕5秒沒響應的時候西永就會快顯視窗)瞭解

 

 

寫一個anr按鈕

在mainactivity裡面寫代碼如下

 

 

 

 

 

 

 

 

 

注意以後不能再activity裡面不能執行耗時的操作,如果出現耗時的操作,應該開線程

Android的程式預設是單線程即為主線程或者是UI線程。

如何開啟線程

開線程有兩種方式

第一種方式

new Thread(){

public void run() {

};

}.start();

第二方式

new Thread(new Runnable() {

@Override

public void run() {

}

}).start();

四、【案例】實現點擊開始按鈕TextView框裡面顯示1+...+100的結果的變化過程

 

1.介面一個編輯框一個按鈕

 

 

2.Mainactivity代碼如下如果不使用訊息處理器會報錯誤

07-13 02:38:25.215: E/AndroidRuntime(21713): android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.只有主線程才可以操作顯示

 

Mainactivity代碼如下:

public class MainActivity extends Activity {

protected static final int UPDATE_SUM = 0;//只是一種標示

private TextView tv_number;

//訊息處理器

public Handler mHandler = new Handler() {

//處理訊息的方法,輸入handle按提示alt+/就可出來

public void handleMessage(android.os.Message msg) {

switch (msg.what) {

case UPDATE_SUM:

int sum = (Integer) msg.obj;

tv_number.setText(sum + "");

break;

default:

break;

}

};

};

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

tv_number = (TextView) findViewById(R.id.tv_number);

}

 

public void add(View v) {

new Thread() {

public void run() {

int i = 0;

int sum = 0;

while (i <= 100) {

i++;

sum += i;

//tv_number.setText(sum+"");  子線程不能操作顯示發訊息給主線程

/**

 * 思路:

 * 1 建立訊息

 * 2 把資料設定給訊息對象

 * 3 發送訊息

 */

Message msg = Message.obtain();//obtain獲得,即擷取訊息

msg.what = UPDATE_SUM;//給訊息設定唯一標示

msg.obj = sum;

mHandler.sendMessage(msg);//訊息發送後就會交給mHanlder裡面的handleMessage()方法

SystemClock.sleep(200);

}

}

}.start();

}

 

 

 

 

五、Android下訊息機制的實現。

 

1、網路通訊協定

Get請求,資料寫在URL的後面,1kb

Post請求資料在實體裡面

六、【案例五】網狀圖片查看器

在Android2.3以下可以直接使用以下代碼讀取網狀圖片,2.3以上必須使用訊息處理器來處理

try {//多學一招alt+shift+z(x,y是大小寫互換)包裹塊來try ...catch

String path = et_path.getText().toString();

// 1 封裝網路路徑  URL注意不是Uri

URL url=new URL(path);

// 2 開啟串連 url.openConnection()

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

//3 設定串連的參數 (逾時時間長度、請求的方式)

conn.setConnectTimeout(10000);

conn.setRequestMethod("get");//小寫是錯的注意了改成GET

//4 判斷響應碼:200成功

if (conn.getResponseCode()==200){

//5 擷取伺服器回送的流資料

InputStream is= conn.getInputStream();

//把流處理成一張圖片  再顯示

Bitmap bitmap=BitmapFactory.decodeStream(is);

//設定圖片顯示

iv.setImageBitmap(bitmap);

}

 

使用訊息處理器以及緩衝圖片全部代碼如下

public class MainActivity extends Activity {

 

private final static String TAG = "MainActivity";

 

protected static final int SUCCESS_GET_IMAGE = 0;

protected static final int ERROR_GET_IMAGE = 1;

private ImageView iv;

private EditText et_path;

 

private Handler mHandler = new Handler(){

public void handleMessage(android.os.Message msg) {

switch (msg.what) {

case SUCCESS_GET_IMAGE:

File file = (File) msg.obj;

//設定圖片的顯示   

iv.setImageURI(Uri.fromFile(file));

break;

case ERROR_GET_IMAGE:

Toast.makeText(getApplicationContext(), "擷取圖片失敗", 0).show();

break;

 

default:

break;

}

};

};

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

et_path = (EditText) findViewById(R.id.et_path);

iv = (ImageView) findViewById(R.id.iv);

}

 

public void get(View v){

 

new Thread(){

public void run() {

try {

String path = et_path.getText().toString();

File file = new File(Environment.getExternalStorageDirectory(),getFileName(path));

//判斷圖片是否存在

if(file.exists()){

//直接使用

Log.i(TAG, "使用了緩衝的圖片");

Message msg = Message.obtain();

msg.what = SUCCESS_GET_IMAGE;

msg.obj = file;

mHandler.sendMessage(msg);

}else{

//1 封裝網路路徑  URL

URL url = new URL(path);

//2 開啟串連 url.openConnection()

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

//逾時時間長度

conn.setConnectTimeout(5000);

//請求的方式

conn.setRequestMethod("GET");

//4 判斷響應碼:200成功

if(conn.getResponseCode() == 200){

//5 擷取伺服器回送的流資料

InputStream is = conn.getInputStream();

 

//把流處理成一張圖片  再顯示

Bitmap bitmap = BitmapFactory.decodeStream(is);//使用位元影像工廠處理為圖片

 

//緩衝在sdcard

FileOutputStream stream = new FileOutputStream(file);

//format 圖片的格式

//quality 圖片的品質

//stream 輸出資料流

bitmap.compress(CompressFormat.JPEG, 100, stream);

 

Log.i(TAG, "下載了圖片,並且緩衝到了sdcard");

 

 

//發訊息給主線程

Message msg = Message.obtain();

msg.what = SUCCESS_GET_IMAGE;

msg.obj = file;

mHandler.sendMessage(msg);

}else{

Message msg = Message.obtain();

msg.what = ERROR_GET_IMAGE;

mHandler.sendMessage(msg);

}

}

 

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

Message msg = Message.obtain();

msg.what = ERROR_GET_IMAGE;

mHandler.sendMessage(msg);

}

};

}.start();

}

//擷取檔案的名字

public String getFileName(String path){

return path.substring(path.lastIndexOf("/")+1);

}

 

@Override

public boolean onCreateOptionsMenu(Menu menu) {

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.activity_main, menu);

return true;

}

 

}

3.使用SmartImageView 開源空間擷取網頁圖片,將loopj.android.image包複製到src目錄下另外布局裡面的標籤要改成loopj.android.image.SmartImageView即包名加上SmartImageView

iv.setImageUrl("http://10.0.2.2:8080/tomcat.png");

 

 

七、從伺服器上擷取json資料

InputStream is = conn.getInputStream();//其實是一個json格式的字串

 

//如何把json格式的字串 轉化為對象集合

//1 把流變為字串

//2 把字串變為JSONArray

ByteArrayOutputStream bos = new ByteArrayOutputStream();

byte[] buffer = new byte[1024];

int len = 0;

while((len = is.read(buffer)) != -1){

bos.write(buffer, 0, len);

}

String json = bos.toString();

bos.close();

is.close();

 

 

//2 把字串變為JSONArray

JSONArray array = new JSONArray(json);

for(int i = 0;i<array.length();i++){

JSONObject jsonObject = array.getJSONObject(i);

int id = jsonObject.getInt("id");

String name = jsonObject.getString("name");

int age = jsonObject.getInt("age");

Log.i(TAG, "id:"+id+",name:"+name+",age:"+age);

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.