Android 4主線程訪問網絡

最近做一個Android項目,利用Jsoup讀取和解析網頁數據,同樣的程序在Android2.3上運行完全正常,而跑到Android4上面,bug出現了...

看了一下異常:android.os.NetworkOnMainThreadException

然後,上網搜索一下才發現,原來Android4默認情況下是不允許在主線程中訪問網絡的。


解決問題的思路有兩種:

1、解除主線程網絡訪問限制,參見http://developer.android.com/reference/android/os/StrictMode.html

在onCreate中加入以下代碼即可:

 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskReads()
                 .detectDiskWrites()
                 .detectNetwork()   // or .detectAll() for all detectable problems
                 .penaltyLog()
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 .detectLeakedSqlLiteObjects()
                 .detectLeakedClosableObjects()
                 .penaltyLog()
                 .penaltyDeath()
                 .build());

不過如果要求至少是API-9纔可以,否則會編譯器提示錯誤,所以在適配一些低版本系統時候不太給力。


2、多線程中訪問網絡-既然系統默認不允許在主線程中訪問,那麼再開一個線程好了,這樣在處理複雜流程的時候也不會影響界面的流暢,用戶體驗也好。

以下是一段測試代碼:

public class MainActivity extends Activity {

	private Button btnTest;
	private Button btnClear;
	private TextView txtResult;
	private Handler handler = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
		// .detectDiskReads()
		// .detectDiskWrites()
		// .detectNetwork() // or .detectAll() for all detectable problems
		// .penaltyLog()
		// .build());
		// StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
		// .detectLeakedSqlLiteObjects()
		// .detectLeakedClosableObjects()
		// .penaltyLog()
		// .penaltyDeath()
		// .build());

		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		btnTest = (Button) findViewById(R.id.btnTest);
		btnClear = (Button) findViewById(R.id.btnClear);
		txtResult = (TextView) findViewById(R.id.txtResult);
		//
		handler = new Handler() {
			public void handleMessage(Message msg) {
				super.handleMessage(msg);
				if (msg.what == 0) {
					txtResult.append("\nBegin test >>\n");
				} else if (msg.what == 1) {
					txtResult.append(msg.obj.toString());
				} else if (msg.what == 2) {
					txtResult.append("\n<<End test\n");
				}
			}
		};
		//
		txtResult.setText("");
		txtResult.setMovementMethod(ScrollingMovementMethod.getInstance());

		btnTest.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				// doTest();
				doTestOnAndroid4();
			}
		});
		btnClear.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				doClear();

			}
		});

	}

	protected void doClear() {
		txtResult.setText("");

	}

	protected void doTest() {

		String url = "http://www.baidu.com/";
		txtResult.append("\nBegin test >>\n");
		String text = "";
		try {
			text = Jsoup.connect(url).get().toString();
		} catch (Exception e) {
			e.printStackTrace();
			// text = e.getMessage();
		}
		txtResult.append(text);
		txtResult.append("\n<<End test\n");
	}

	protected void doTestOnAndroid4() {

		new Thread(new Runnable() {
			@Override
			public void run() {
				Message m = new Message();
				m.what = 0;
				handler.sendMessage(m);
				//
				m = new Message();
				m.what = 1;
				String url = "http://www.baidu.com/";
				try {
					m.obj = Jsoup.connect(url).get().toString();
				} catch (Exception e) {
					e.printStackTrace();
					// m.obj = e.getMessage();
				}
				handler.sendMessage(m);
				//
				m = new Message();
				m.what = 2;
				handler.sendMessage(m);
			}
		}).start();

	}

}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章