Android學習系列筆記(四)

##Android基礎網絡第一天html

01 網絡html源碼查看器

訪問網絡須要加Internet權限:
android.permission.INTERNET 

	
使用UrlConnection請求一個url地址獲取內容:

		//1.建立一個Url對象
			URL url = new URL(url_str);
		//2.獲取一個UrlConnection對象
			HttpURLConnection connection = (HttpURLConnection)url.openConnection();
		//3.爲UrlConnection對象設置一些請求的參數,請求方式,鏈接的超時時間 
			connection.setRequestMethod("GET");//設置請求方式
			connection.setConnectTimeout(1000*10);//設置超時時間
		//4.在獲取url請求的數據前須要判斷響應碼,200 :成功,206:訪問部分數據成功   300:跳轉或重定向  400:錯誤 500:服務器異常
			int code = connection.getResponseCode();
			if(code == 200){
		//5.獲取有效數據,並將獲取的流數據解析成String
				InputStream inputStream = connection.getInputStream();
				String result = StreamUtils.streamToString(inputStream);



注意事項:
	
	1. ANR:application not response 應用無響應; androoid中耗時的操做(請求網絡,大文件的拷貝,數據庫的操做)須要在子線程中作。
	09-02 01:52:40.711: E/ActivityManager(857): ANR in com.itheima.sourcelook (com.itheima.sourcelook/.MainActivity)

	2. 4.0後網絡操做強制在子線程中進行。由於網絡訪問是耗時的操做,可能會致使ANR
	09-02 01:57:32.879: W/System.err(1789):  android.os.NetworkOnMainThreadException

	3.錯誤線程調用異常,子線程不可以更新UI(控件的內容)
		09-02 02:02:08.873: W/System.err(1858): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.


	主線程不可以作耗時的操做,網絡請求就是耗時的操做須要放到子線程作。子線程不能更新控件的內容(更新Ui)。因此產生了矛盾,解決辦法就是使用Handler.

02 消息機制的寫法(重要) Handler

使用Handler的步驟:

	1.主線程中建立一個Handler
	private Handler handler = new Handler(){
			public void handleMessage(android.os.Message msg) {
	
	
			};
	};

	2.重寫handler的handlermessage方法

	3.子線程中建立一個Message對象,將獲取的數據綁定給msg
			Message msg = new Message();
			//另外一種方式:Message msg = Messge.obtain;
			msg.obj = result;
	4.主線程中的handler對象在子線程中將message發送給主線程
			handler.sendMessage(msg);
	
	5.主線程中handlermessage方法接受子線程發來的數據,就能夠作更新UI的操做。
			
		
***********主線程
	
//☆☆☆1.在主線程中建立一個Handler對象
private Handler handler = new Handler(){
	//☆☆☆2.重寫handler的handlermessage方法,用來接收子線程中發來的消息
	public void handleMessage(android.os.Message msg) {
		//☆☆☆5.接收子線程發送的數據,處理數據。
		Bitmap bitmap  = (Bitmap) msg.obj;
		//☆☆☆6.當前方法屬於主線程能夠作UI的更新
		//五.獲取服務器返回的內容,顯示到textview上
		img_pic.setImageBitmap(bitmap);//設置ImageView的圖片內容
	};
};

************子線程

		if(code == 200){
			//5.獲取有效數據,並將獲取的流數據解析成String
					InputStream inputStream = connection.getInputStream();
					
					//將一個讀取流轉換成一個圖片 Drawable , Btimap:位圖  ?????
					Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
					
					
					//☆☆☆3.子線中建立一個Message對象,爲了攜帶子線程中獲取的數據給主線程。
					Message msg = Message.obtain();//獲取一個Message對象,內部實現是:若是以前的Message存在直接返回,不存在建立新的Message返回
					msg.obj = bitmap;//將獲取的數據封裝到msg中。
					//☆☆☆4.使用handler對象將message發送到主線程。
					handler.sendMessage(msg);
		
					
				}

03 消息機制原理(重要)

有幾個主要元素:

1.Message:用來攜帶子線程中的數據。
2.MessageQueue:用來存放全部子線程發來的Message.
3.Handler:用來在子線程中發送Message,在主線程中接受Message,處理結果
4.Looper:是一個消息循環器,一直循環遍歷MessageQueue,從MessageQueue中取一個Message,派發給Handler處理。

原理看資料中的圖。

04 網絡圖片查看器

adb shell+  input text 內容;能夠經過將內容輸入到手機上的輸入框。

	將一個讀取流轉換成bitmap對象:

	BitmapFactory:能夠將文件,讀取流,字節數組轉換成一個Bitmap對象。
	Bitmap bitmap = BitmapFactory.decodeStream(InputStream in);
	
	imageView.setImageBitmap(bitmap);//設置圖片內容

05 常見消息處理api(重要)

面試:子線程必定不能更新UI? SurfaceView :多媒體視頻播放 ,能夠在子線程中更新UI; Progress(進度)相關的控件:也是能夠在子線程中更新Ui;審計機制:activity徹底顯示的時候審計機制纔會去檢測子線程有沒有更新Ui.
	

	1.使用activity的runOnUiThread方法更新ui,不管當前線程是不是主線程,都將在主線程執行.
			runOnUiThread(new Runnable() {
				
				[@Override](https://my.oschina.net/u/1162528)
				public void run() {
					tv_simple.setText("我被更新了");
				}
			});

	2.使用handler直接post到主線程,handler須要在主線程建立
				//延遲多少毫米執行runnable。
				mHandler.postDelayed(new Runnable() {
				
				[@Override](https://my.oschina.net/u/1162528)
				public void run() {

					tv_simple.setText("我被更新了");
				}
			}, 1000*5);

		應用場景:廣告展現後,作頁面跳轉。

06 新聞客戶端案例(重要) 項目 和 產品

第一次進入新聞客戶端須要請求服務器獲取新聞數據,作listview的展現,爲了第二次再次打開新聞客戶端時能快速顯示新聞,須要將數據緩存到數據庫中,下次打開能夠直接去數據庫中獲取新聞直接作展現。


	1.寫佈局listview  ok

	2.找到listview,設置條目的點擊事件。  ok

	3.獲取數據提供給listview作展現。

		3.1:獲取本地數據庫緩存的新聞數據,讓listview顯示。若是沒有網絡不至於顯示空界面。
		3.2:請求服務器獲取新聞數據,是一個json字符串,須要解析json,封裝到list集合中。提供給listview展現。

		public static String newsPath_url = "http://192.168.13.83:8080/itheima74/servlet/GetNewsServlet";
//封裝新聞的假數據到list中返回
public static ArrayList<NewsBean> getAllNewsForNetWork(Context context) {
	ArrayList<NewsBean> arrayList = new ArrayList<NewsBean>();
	try{
		//1.請求服務器獲取新聞數據
		//獲取一個url對象,經過url對象獲得一個urlconnnection對象
		URL url = new URL(newsPath_url);
		HttpURLConnection connection = (HttpURLConnection) url.openConnection();
		//設置鏈接的方式和超時時間
		connection.setRequestMethod("GET");
		connection.setConnectTimeout(10*1000);
		//獲取請求響應碼
		int code = connection.getResponseCode();
		if(code == 200){
			//獲取請求到的流信息
			InputStream inputStream = connection.getInputStream();
			String result = StreamUtils.streamToString(inputStream);
			
			//2.解析獲取的新聞數據到List集合中。
			
				JSONObject root_json = new JSONObject(result);//將一個字符串封裝成一個json對象。
				JSONArray jsonArray = root_json.getJSONArray("newss");//獲取root_json中的newss做爲jsonArray對象
				
				for (int i = 0 ;i < jsonArray.length();i++){//循環遍歷jsonArray
					JSONObject news_json = jsonArray.getJSONObject(i);//獲取一條新聞的json
					
					NewsBean newsBean = new NewsBean();
					
					newsBean. id = news_json.getInt("id");
					newsBean. comment = news_json.getInt("comment");//評論數
					newsBean. type = news_json.getInt("type");//新聞的類型,0 :頭條 1 :娛樂 2.體育
					newsBean. time = news_json.getString("time");
					newsBean. des = news_json.getString("des");
					newsBean. title = news_json.getString("title");
					newsBean. news_url = news_json.getString("news_url");
					newsBean. icon_url = news_json.getString("icon_url");
					
					arrayList.add(newsBean);
		
				}

			//3.清楚數據庫中舊的數據,將新的數據緩存到數據庫中
				new NewsDaoUtils(context).delete();
				new NewsDaoUtils(context).saveNews(arrayList);
		}
		
	}catch (Exception e) {
		e.printStackTrace();
	}
	return arrayList;
}

		3.3: 獲取服務端數據成功後,須要緩存到本地數據庫,緩存前須要清空本地數據庫。

	4.建立一個Adapter繼承BaseAdapter,封裝4個方法,須要接收穫取的新聞數據   ok


	5.將adapter設置給listview。   ok

07 採用smartimageview 顯示(開源的小項目)

github : 12306 出名

自定義的控件在佈局文件中的引用都須要指定類的完整路徑

08 smartimageview 的原理

1.自定義了一個MyImageview類繼承了Imageview,添加三個構造方法

2.添加一個setImageUrl方法接受一個圖片url
	
3.新建一個子線程去請求url獲取圖片資源

4.將獲取的圖片Bitmap經過handler發送給主線程,主線程設置給當前view.

5.在佈局中引用MyImageview,須要指定完成的包名路徑。

09 get方式提交數據到服務器

10 post方式提交數據到服務器

get方式和post方式的區別:

	1.請求的URL地址不一樣:
		post:"http://192.168.13.83:8080/itheima74/servlet/LoginServlet"
		get:http://192.168.13.83:8080/itheima74/servlet/LoginServlet?username=root&pwd=123

	2.請求頭不一樣:
		****post方式多了幾個請求頭:Content-Length   Cache-Control  Origin

		openConnection.setRequestProperty("Content-Length", body.length()+"");
		openConnection.setRequestProperty("Cache-Control", "max-age=0");
		openConnection.setRequestProperty("Origin", "http://192.168.13.83:8080");

		****post方式還多了請求的內容:username=root&pwd=123

			//設置UrlConnection能夠寫請求的內容
		openConnection.setDoOutput(true);
		//獲取一個outputstream,並將內容寫入該流
		openConnection.getOutputStream().write(body.getBytes());

	3.請求時攜帶的內容大小不一樣
		get:1k 
		post:理論無限制
相關文章
相關標籤/搜索