天天看點

Android 網頁源碼檢視器(URLConnection以及handler助手)

public class MainActivity extends AppCompatActivity {


    protected static final int REQUESTSUCCESS = 0;
    protected static final int REQUESTNOTFOUND = 1;
    protected static final int REQUESTEXCEPTION = 2;

    private EditText et_path;
    private TextView tv_result;

    //在主線程中定義一個handler
    private Handler handler = new Handler(){
        //這個方法是在主線程裡面執行的
        public void handleMessage(Message msg) {
            // 是以就可以在主線程裡面更新UI了
            //1區分一下發送的是哪條消息
            switch (msg.what) {
                case REQUESTSUCCESS: //代表請求成功
                    String content = (String) msg.obj;
                    tv_result.setText(content);
                    break;
                case REQUESTNOTFOUND: //代表請求失敗
                    Toast.makeText(getApplicationContext(), "請求資源不存在", Toast.LENGTH_SHORT).show();
                    break;
                case REQUESTEXCEPTION: //代表請求異常
                    Toast.makeText(getApplicationContext(), "伺服器忙", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //1 找到我們關心的控件
        et_path = (EditText) findViewById(R.id.et_path);
        tv_result = (TextView) findViewById(R.id.tv_result);

        //1.1 列印目前線程的名字
    }

    //2 點選按鈕進行檢視 指定路徑的源碼
    public void click(View v) {
        //2.0 建立一個子線程  耗時的操作全都放在子線程裡!
        new Thread(){public void run(){
            try {
                //2.1 擷取源代碼路徑
                String path = et_path.getText().toString().trim(); //注意這裡www.baidu.com前面要加上協定,不然會報無協定異常!!
                //2.2 建立URL 對象指定我們要通路的網址(路徑)
                URL url = new URL(path);
                //2.3 拿到httpurlconnection對象 用于發送或者接收資料
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                //2.4 設定發送GET請求
                conn.setRequestMethod("GET"); //GET要求大寫 預設就是GET請求
                //2.5 設定請求逾時時間
                conn.setConnectTimeout(5000);
                //2.6 擷取伺服器傳回的狀态碼
                int code = conn.getResponseCode();
                //2.7 如果code == 200 說明請求成功
                if (code == 200) {
                    //2.8 擷取伺服器傳回的資料 是以流的形式傳回的 由于把流轉換成字元串是一個非常常見的操作,是以我抽出一個工具類StreamTools
                    InputStream in = conn.getInputStream();
                    //2.9 使用我們定義的工具類 把in轉換成String
                    String content = StreamTools.readStream(in);
                    //2.9.0 建立message對象
                    Message msg = new Message();
                    msg.what = REQUESTSUCCESS;
                    msg.obj = content;
                    //2.9.1 拿着我們建立的handle(助手) 告訴系統 說我要更新UI
                    handler.sendMessage(msg); //發了一條消息 消息(msg)裡把資料放到了msg裡, handleMessage方法就會執行
                    //2.9.1 把流裡面的資料展示到textview上,這句話就屬于更新UI的邏輯, 好像更新UI得去主線程吧。
//                    tv_result.setText(content);
                } else {
                    //請求資源不存在 Toast是一個view 也不能在該線程更新UI
                    Message msg = new Message();
                    msg.what = REQUESTNOTFOUND; // 代表哪條消息
                    handler.sendMessage(msg);
                }
            } catch (Exception e) {
                e.printStackTrace();
                Message msg = new Message();
                msg.what = REQUESTEXCEPTION; // 代表哪條消息
                handler.sendMessage(msg); //發送消息
            }
        }}.start();
    }
}      
public class StreamTools {

    //把一個InputStream 轉換成一個Stream
    public static String readStream(InputStream in) throws Exception{
        //定義一個記憶體輸出流
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int len = -1;
        byte[] buffer = new byte[1024]; // 1kb
        while ((len=in.read(buffer))!=-1) {
            baos.write(buffer, 0, len);
        }
        in.close();
        String content = new String(baos.toByteArray());
        return content;
    }
}