1.寫一個網(wǎng)絡(luò)源碼查看器
思路:
1.寫布局 EditText Button TextView ok
2.找控件饮六,設(shè)置點擊事件 ok
3.在點擊事件的onclick中浅萧,獲取用戶輸入的url ok
4.訪問url,獲取源碼 ********* 不ok
//4.1 創(chuàng)建一個URL對象;
URL url = new URL(url_str);
//4.2 通過url對象獲取一個HttpUrlConnection對象
HttpURLConnection cn = (HttpURLConnection) url.openConnection();
//4.3 為HttpUrlConnection對象設(shè)置一些參數(shù) . 如:網(wǎng)絡(luò)請求方式 路捧,連接的超時時間
cn.setRequestMethod("GET");//設(shè)置網(wǎng)絡(luò)的請求方式 GET ,POST一定 要大寫
cn.setConnectTimeout(10*1000);//設(shè)置網(wǎng)絡(luò)連接的超時時間
//4.4 獲取網(wǎng)絡(luò)的響應(yīng)狀態(tài)碼
int code = cn.getResponseCode();//獲取服務(wù)器的響應(yīng)碼
//4.5判斷狀態(tài)碼是否是200慢显,如果是200 獲取流數(shù)據(jù)
if(code == 200){
InputStream inputStream = cn.getInputStream();//獲取一個讀取流讀取服務(wù)器返回的數(shù)據(jù)
//4.6 將獲取的流數(shù)據(jù)轉(zhuǎn)換成字符串持际,就是我們所需的源碼
String result = Utils.StreamToString(inputStream);
//5.將源碼顯示到TextView上
tv_source.setText(result);
}
5.將源碼顯示到TextView上
2.出現(xiàn)的問題
1.注意添加網(wǎng)絡(luò)訪問權(quán)限:
2.ANR: 多次點擊按鈕會出現(xiàn)application not response應(yīng)用無響應(yīng)的異常;
安卓規(guī)定耗時的操作(網(wǎng)絡(luò)請求,大文件的拷貝殴蹄,數(shù)據(jù)庫的操作)需要放到子線程中執(zhí)行究抓,不能在主線程中執(zhí)行.4.0以后android強制要求網(wǎng)絡(luò)請求必須放到子線程中執(zhí)行,android4.0之后會報錯誤:NetworkOnMainThreadException袭灯;
11-01 02:44:12.618: E/ActivityManager(858): ANR in com.itheima.sourcelook (com.itheima.sourcelook/.MainActivity)
3.NetworkOnMainThreadException 網(wǎng)絡(luò)訪問在主線程異常
11-01 02:47:40.231: W/System.err(1806): android.os.NetworkOnMainThreadException
4.當(dāng)創(chuàng)建了子線程并將操作放入子線程之后會報CalledFromWrongThreadException 錯誤的線程調(diào)用異常 ,只有主線程才能夠更新UI刺下,子線程不能更新UI(改變控件的內(nèi)容或樣式)。
11-01 02:56:07.750: W/System.err(1947): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
結(jié)論:耗時的操作需要放到子線程中執(zhí)行稽荧,不能在主線程中執(zhí)行橘茉;只有主線程才能更新UI,子線程獲取到數(shù)據(jù)不能直接更新UI.產(chǎn)生了矛盾姨丈。畅卓。如何解決? Handler
3.handler消息機制
思路:
1.在主線程創(chuàng)建一個Handler對象蟋恬,成員變量翁潘。
new Handler()
2.重新handler對象的handlerMessage方法
new Handler(){
handlerMessage(Message msg){
}
}
3.在子線程中創(chuàng)建一個Message對象。
Message msg = new Message();
4.將子線程獲取的結(jié)果綁定給Message對象
msg.obj = result;
5.子線程中使用主線程創(chuàng)建的handler將Message對象發(fā)送到主線程
handler.sendMessage(msg);
6.主線程中的handler對象的handlerMessage方法接受子線程發(fā)來的Message對象歼争,可以獲取Message對象中綁定的數(shù)據(jù)拜马,做UI更新
new Handler(){
handlerMessage(Message msg){
String result = msg.obj;
textview.setText(result);
}
}
4.網(wǎng)絡(luò)圖片查看器
BitmapFactory 可以將各種各樣的資源(文件渗勘,流,二進(jìn)制數(shù)組)轉(zhuǎn)換成一個Bitmap對象俩莽。
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
代碼:
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//2.找控件旺坠,寫點擊事件
et_url = (EditText) findViewById(R.id.et_url);
img_pic = (ImageView) findViewById(R.id.img_pic);
findViewById(R.id.bt_getpic).setOnClickListener(this);
System.out.println("oncreate:"+Thread.currentThread().getName());
}
//☆☆☆☆☆? 1.在主線程中創(chuàng)建一個Handler對象
privateHandler handler =newHandler(){
//☆☆☆☆☆? 2.復(fù)寫Handler對象的一個handlerMessage方法
publicvoidhandleMessage(android.os.Message msg) {
//☆☆☆☆☆? 6.在主線程的handler對象中的handleMessage方法接受子線程發(fā)來的Message對象,并獲取綁定的數(shù)據(jù)豹绪;那么主線程就可以更新UI了价淌。
Bitmap bm? = (Bitmap) msg.obj;
// 當(dāng)前線程為主線程,可以更新Ui
//5.將bitmap設(shè)置給Imageview做展示
img_pic.setImageBitmap(bm);
};
};
@Override
publicvoidonClick(View v) {
//創(chuàng)建一個子線程
newThread(newRunnable() {
@Override
publicvoidrun() {
System.out.println("runnable:"+Thread.currentThread().getName());
//3.在點擊事件的onclick中瞒津,獲取用戶輸入的url? ok
String url_str = et_url.getText().toString().trim();
try{
//4.訪問url,獲取源碼????????????? ********* 不ok
//4.1 創(chuàng)建一個URL對象蝉衣;
URL url =newURL(url_str);
//4.2 通過url對象獲取一個HttpUrlConnection對象
HttpURLConnection cn = (HttpURLConnection) url.openConnection();
//4.3? 為HttpUrlConnection對象設(shè)置一些參數(shù) .?? 如:網(wǎng)絡(luò)請求方式 ,連接的超時時間
cn.setRequestMethod("GET");//設(shè)置網(wǎng)絡(luò)的請求方式 GET ,POST一定 要大寫
cn.setConnectTimeout(10*1000);//設(shè)置網(wǎng)絡(luò)連接的超時時間
//4.4 獲取網(wǎng)絡(luò)的響應(yīng)狀態(tài)碼
intcode = cn.getResponseCode();//獲取服務(wù)器的響應(yīng)碼
//4.5判斷狀態(tài)碼是否是200巷蚪,如果是200 獲取流數(shù)據(jù)
if(code == 200){
InputStream inputStream = cn.getInputStream();//獲取一個讀取流讀取服務(wù)器返回的數(shù)據(jù)
//4.6 將獲取的流數(shù)據(jù)轉(zhuǎn)換成圖片資源?? Drawable Bitmap:位圖
//使用BitmapFactory將各種資源(流病毡,文件,二進(jìn)制數(shù)組)轉(zhuǎn)換成圖片對象Bitmap
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
//☆☆☆☆☆? 3.在子線程中創(chuàng)建一個Message對象
Message msg =newMessage();
//☆☆☆☆☆? 4.將子線程中獲取的數(shù)據(jù)綁定給Message對象
msg.obj = bitmap;
//☆☆☆☆☆? 5.使用主線程中的handler對象將綁定數(shù)據(jù)的Message對象發(fā)送到主線程
handler.sendMessage(msg);
}
}catch(Exception e) {
e.printStackTrace();
}
}
}).start();
}
5.設(shè)計自己的SmartImageView控件(可以通過URI設(shè)置控件顯示的圖片)
思路:
1.通過httpurlconnection連接網(wǎng)絡(luò)資源
2.通過bitmapfactory獲得bitmap(factory可以通過流轉(zhuǎn)換bitmap)
3.建立message
4.用handler傳遞message獲得bitmap
5.在自己的控件中顯示
注意:
自定義控件:
1.寫一個類繼承ImageView,寫三個構(gòu)造方法
2.寫一個setImageUrl方法屁柏,請求url地址啦膜,獲取圖片流,轉(zhuǎn)換成bitmap,設(shè)置給當(dāng)前類的對象淌喻。
3.在布局文件中引用自定義的MySmartImageView ,注意僧家,引用時,需要指定類的完整路徑裸删。
代碼
publicclassMySmartImageViewextendsImageView{
Handlerhand=newHandler(){
publicvoidhandleMessage(Message msg) {
Bitmap img=(Bitmap) msg.obj;
//自定義控件標(biāo)簽要寫全包名
//
//android:layout_height="68dp"
//android:layout_width="68dp"
//android:layout_margin="10dp"
//android:id="@+id/iv_view"
//android:src="@drawable/ic_launcher"/>
MySmartImageView.this.setImageBitmap(img);
};
};
//一定要復(fù)寫3個方法八拱,否則運行會報錯
publicMySmartImageView(Context context, AttributeSet attrs,intdefStyle) {
super(context, attrs, defStyle);
//TODOAuto-generated constructor stub
}
publicMySmartImageView(Context context, AttributeSet attrs) {
super(context, attrs);
//TODOAuto-generated constructor stub
}
publicMySmartImageView(Context context) {
super(context);
//TODOAuto-generated constructor stub
}
publicvoidSetImageUrl(String url)
{
finalString url2=url;
newThread(newRunnable() {
@Override
publicvoidrun() {
try{
URL url1=newURL(url2);
HttpURLConnection con=(HttpURLConnection) url1.openConnection();
con.setReadTimeout(10000);
con.setRequestMethod("GET");
if(con.getResponseCode()==200)
{
InputStream in=con.getInputStream();
Bitmap img=BitmapFactory.decodeStream(in);
Message msg=newMessage();
msg.obj=img;
hand.sendMessage(msg);
}
}catch(MalformedURLException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}catch(IOException e) {
//TODOAuto-generated catch block
e.printStackTrace();
}
//TODOAuto-generated method stub
}
}).start();
}
}
6.常見消息處理API
1.子線程可以更新UI的情況
//面試:: 審計機制 ,在activity完全顯示之后才會工作涯塔,才會檢測是否在子線程中更新UI肌稻,顯示之前更新UI審計機制不會工作。
// 還有一些情況可以在子線程更新Ui匕荸,如SurfaceView和與進(jìn)度條相關(guān)的控件都可以在子線程更新UI爹谭。
代碼:
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_text= (TextView)findViewById(R.id.tv_text);
//SystemClock.sleep(5000);
newThread(newRunnable() {
publicvoidrun() {
SystemClock.sleep(5000);
tv_text.setText("我被更新了");
}
}).start();
}
2.runOnUiThread方法:無論當(dāng)前線程是否是主線程,都會被在主線程中執(zhí)行
//在activity中有一個runOnUIthread方法,UI線程就是主線程無論要運行的動作是否是主線程榛搔,都將會在主線程運行诺凡。
runOnUiThread(new Runnable() {
@Override
public void run() {
tv_simple.setText("我被更新了");
}
});
3.handler 的post方法
//使用handler 的post方法將一個動作發(fā)送到主線程去執(zhí)行。 這個handler必須定義在主線程
handler.post(new Runnable() {
@Override
public void run() {
tv_simple.setText("我被更新了");
}
});
4.handler 的postDelaed方法践惑,發(fā)送一個延遲的動作到主線程绑洛,特別適合做廣告展示。
//delayMillis:延遲的時間
handler.postDelayed(new Runnable() {
@Override
public void run() {
tv_simple.setText("我被更新了");
}
}, 5000);
7.android的Json解析
1.android自帶Json封裝API
String result = Utils.StreamToString(inputStream);//獲得一個Json字符串
//6.解析json字符串童本,封裝到list中
JSONObject root_json = new JSONObject(result);//將一個json字符串轉(zhuǎn)換成一個jsonObject
//根據(jù)json的key獲取newss這個json數(shù)組
JSONArray jsonArray = root_json.getJSONArray("newss");
//遍歷jsonArray獲取一條條json數(shù)據(jù)
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject newsJson = jsonArray.getJSONObject(i);//根據(jù)索引獲取數(shù)組中的一個json對象
NewsBean bean = new NewsBean();
bean.id = newsJson.getInt("id");
bean.comment = newsJson.getInt("comment");
bean.type = newsJson.getInt("type");
bean.title = ???? newsJson.getString("title");
bean.des = ???? newsJson.getString("des");
bean.icon_url = newsJson.getString("icon_url");
bean.news_url = newsJson.getString("news_url");
bean.time = newsJson.getString("time");
arrayList.add(bean);
2.第三方工具包解析介紹(最好選擇Gson)
1.、各個JSON技術(shù)的簡介和優(yōu)劣
1.json-lib
json-lib最開始的也是應(yīng)用最廣泛的json解析工具脸候,json-lib 不好的地方確實是依賴于很多第三方包穷娱,
包括commons-beanutils.jar绑蔫,commons-collections-3.2.jar,commons-lang-2.6.jar泵额,commons-logging-1.1.1.jar配深,ezmorph-1.0.6.jar,
對于復(fù)雜類型的轉(zhuǎn)換嫁盲,json-lib對于json轉(zhuǎn)換成bean還有缺陷篓叶,比如一個類里面會出現(xiàn)另一個類的list或者map集合,json-lib從json到bean的轉(zhuǎn)換就會出現(xiàn)問題羞秤。
json-lib在功能和性能上面都不能滿足現(xiàn)在互聯(lián)網(wǎng)化的需求缸托。
2.開源的Jackson
相比json-lib框架,Jackson所依賴的jar包較少瘾蛋,簡單易用并且性能也要相對高些俐镐。
而且Jackson社區(qū)相對比較活躍,更新速度也比較快哺哼。
Jackson對于復(fù)雜類型的json轉(zhuǎn)換bean會出現(xiàn)問題佩抹,一些集合Map,List的轉(zhuǎn)換出現(xiàn)問題取董。
Jackson對于復(fù)雜類型的bean轉(zhuǎn)換Json棍苹,轉(zhuǎn)換的json格式不是標(biāo)準(zhǔn)的Json格式
3.Google的Gson
Gson是目前功能最全的Json解析神器,Gson當(dāng)初是為因應(yīng)Google公司內(nèi)部需求而由Google自行研發(fā)而來茵汰,
但自從在2008年五月公開發(fā)布第一版后已被許多公司或用戶應(yīng)用枢里。
Gson的應(yīng)用主要為toJson與fromJson兩個轉(zhuǎn)換函數(shù),無依賴经窖,不需要例外額外的jar坡垫,能夠直接跑在JDK上。
而在使用這種對象轉(zhuǎn)換之前需先創(chuàng)建好對象的類型以及其成員才能成功的將JSON字符串成功轉(zhuǎn)換成相對應(yīng)的對象。
類里面只要有g(shù)et和set方法闺魏,Gson完全可以將復(fù)雜類型的json到bean或bean到j(luò)son的轉(zhuǎn)換操灿,是JSON解析的神器。
Gson在功能上面無可挑剔溉卓,但是性能上面比FastJson有所差距。
4.阿里巴巴的FastJson
Fastjson是一個Java語言編寫的高性能的JSON處理器,由阿里巴巴公司開發(fā)搬泥。
無依賴桑寨,不需要例外額外的jar,能夠直接跑在JDK上忿檩。
FastJson在復(fù)雜類型的Bean轉(zhuǎn)換Json上會出現(xiàn)一些問題尉尾,可能會出現(xiàn)引用的類型,導(dǎo)致Json轉(zhuǎn)換出錯燥透,需要制定引用沙咏。
FastJson采用獨創(chuàng)的算法辨图,將parse的速度提升到極致,超過所有json庫肢藐。
綜上4種Json技術(shù)的比較故河,在項目選型的時候可以使用Google的Gson和阿里巴巴的FastJson兩種并行使用,
如果只是功能要求吆豹,沒有性能要求鱼的,可以使用google的Gson,
如果有性能上面的要求可以使用Gson將bean轉(zhuǎn)換json確保數(shù)據(jù)的正確痘煤,使用FastJson將Json轉(zhuǎn)換Bean
Gson解析: