在JellyBean中使用WebView和HTTPClient进行线程化

时间:2013-01-30 02:05:44

标签: android webview httpclient

我正在尝试使用HTTPClient调用和URL,修改内容,然后使用webview.loadDataWithBaseURL()设置数据,但是我遇到了线程问题。

如果我在主UI线程上进行HTTPGet调用,则会收到android.os.NetworkOnMainThreadException的致命错误。

如果我在新线程中进行调用,并将值设置为该线程中的webView,我会在日志中收到警告:“必须在UI线程上调用所有WebView方法。未来版本的WebView可能会不支持在其他线程上使用。“

如果我在一个单独的线程中进行调用并将其设置在类变量中并发布到主线程上的webView,那么loadDataWithBaseURL()不会获取我在单独线程中调用的数据,因为它似乎发生在另一个线程完成调用之前。

所以问题是:如何在单独的线程中获取内容,并将它们加载到主线程的webView中?

public class Browser extends Activity {
public final String CLASS_TAG = "ScoutBrowser";
public WebView webView;
final Activity activity = this;
public String webContent;


/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.getWindow().requestFeature(Window.FEATURE_PROGRESS);
    setContentView(R.layout.activity_browser);

    webView = getWebView();


    Log.i(CLASS_TAG, "Loaded App...");
}

private WebView getWebView() {
    WebView view = (WebView) findViewById(R.id.webView);

    view.setWebChromeClient(new WebChromeClient() {

        public void onProgressChanged(WebView view, int progress) {
            activity.setTitle("Loading...");
            activity.setProgress(progress * 100);
            if (progress == 100)
                activity.setTitle(R.string.app_name);
        }
    });

    view.setWebViewClient(new MyViewerClient());
    view.getSettings().setJavaScriptEnabled(true);
    webContent = "<html><body>initialized...</body></html>";
    new Thread(new Runnable() {
           public void run() {
               webContent = callURL();
               WebView view = (WebView) findViewById(R.id.webView);
               view.loadDataWithBaseURL("http://www.somewebsite.com", webContent, "text/html", null, null);

           }
    }).start(); 

    //view.loadDataWithBaseURL("http://www.somewebsite.com", webContent, "text/html", null, null);


    return view;
}

public String callURL(){
    String content = "<html><body>loading...</body></html>";

    //Creates web clientclient
    DefaultHttpClient httpclient = new DefaultHttpClient();

    // Create a local instance of cookie store
    CookieStore cookieStore = new BasicCookieStore();

    // Create local HTTP context
    HttpContext localContext = new BasicHttpContext();
    // Bind custom cookie store to the local context
    localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);

    HttpGet httpget = new HttpGet("http://www.somewebsite.com/"); 

    //System.out.println("executing request " + httpget.getURI());
    Log.d(CLASS_TAG,"executing request " + httpget.getURI());


    // Pass local context as a parameter
    try {
        HttpResponse response = httpclient.execute(httpget, localContext);

        int code = response.getStatusLine().getStatusCode();
        String reason = response.getStatusLine().getReasonPhrase();
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            InputStream instream = entity.getContent();

            content = convertInputStream(instream);
            //tv.setText(content);

        }

        Log.d(CLASS_TAG,"Response Code: "+code+" - "+reason);


    } catch (ClientProtocolException e) {
        Log.e(CLASS_TAG,"ProtocolException",e);
    } catch (IOException e) {
        Log.e(CLASS_TAG,"IOException",e);
    }
    Log.d(CLASS_TAG, webContent);
    return content;
}

public String convertInputStream(InputStream is) throws IOException{
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
          sb.append(line);
        }
        is.close();
        return sb.toString();
}

}

1 个答案:

答案 0 :(得分:2)

从新线程中的run方法,使用以下方法之一将其发布回UI线程:http://developer.android.com/guide/components/processes-and-threads.html

其他选项是保持一个指向你的线程的变量并在其上调用join(),或者使用FutureTask。