在AsyncTask中出现android.os.NetworkOnMainThreadException异常

9

我意识到当你试图在UI线程上进行某种网络请求时会出现这个错误,但是正如下面的代码所示,实际上我是在AsyncTask中调用Http Get:

public class LeftPaneFragment extends Fragment {

    private ImageView _profileImage;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(wj.tweetTab.R.layout.left_pane, container);

        _profileImage = (ImageView) view.findViewById(R.id.profileImage);

        setUpProfileInfo(view);

        return view;
    }

    private void setUpProfileInfo(View view) {          
        new SetUpUserInfo().doInBackground();
    }

    private class SetUpUserInfo extends AsyncTask<Void, Void, Drawable> {

        @Override
        protected Drawable doInBackground(Void... params) {

            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpGet request = new HttpGet(_model.UserInfo.ProfileImageUrl);

            InputStream inputStream = null;

            try {
                HttpResponse response = httpClient.execute(request);        
                inputStream = response.getEntity().getContent();
            }
            catch (Exception e) {               
                Log.e("setUpUserInfo.doInBackground", e.getMessage());
            }

            return Drawable.createFromStream(inputStream, "src");
        }

        @Override
        protected void onPostExecute(Drawable result) {
            _profileImage.setImageDrawable(result);
        }
    }
}

这里有明显的问题吗?另外,NetworkOnMainThreadException异常除了在主线程中执行http请求之外,还会因为其他原因而抛出吗?

我是一个Android新手,只接触了几天。

2个回答

23

但是从下面的代码中可以看出,我实际上是在一个AsyncTask中调用Http Get方法。

实际上不是这样的。你需要调用execute()而不是直接调用doInBackground(),否则你将不会使用AsyncTask提供的任何框架支持,而且你只是在UI线程中直接调用该方法。


我在使用线程(Start vs. run)时已经多次遇到了这个问题,几乎还有更多的接近情况。为什么doInBackground()会被提供出来,而它又如此无用呢? - user1499731
1
“可用”是什么意思?首先,它是“protected”,这意味着您不应该从AsyncTask之外的类中调用它。不幸的是,许多人只是内联声明AsyncTasks,以便可以(并且确实)调用“doInBackground()”。但是,“execute()”是“public”的。 - dmon

1
也许是Android SDK版本太高了(版本> = 3.0)。
尝试添加代码
import android.os.StrictMode;
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()   
        .detectDiskReads()   
        .detectDiskWrites()   
        .detectNetwork()   // or .detectAll() for all detectable problems   
        .penaltyLog()   
        .build());  

onCreateView()函数中;


1
这是不好的做法。他们添加了这个模式,以便人们不会在UI线程上编写与网络相关的内容。这只是一个比黑客高一步的解决方法。正确编码才是更好的解决方案。 - WORMSS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接