Android 后台方法中的 NetworkOnMainThreadException

Android NetworkOnMainThreadException in Background Methods

我的应用程序中有一些网络请求,每当调用网络相关代码时,我都会遇到此异常。我已经把它们放在后台了:

    @Background
    protected void getBitmapFromURL(String src, ImageView img) {
        try {
            URL url = new URL(src);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
            updateImageView(BitmapFactory.decodeStream(input), img);
            return;
        } catch (IOException e) {
            System.out.println("************** network exception: download image failed");
            return;
        }
    }

    @UiThread
    protected void updateImageView(Bitmap bitmap, ImageView img) {
        img.setImageBitmap(bitmap);
        return;
    }

但错误依然存在。我在这里实现了我自己的适配器,它扩展了 BaseAdapter。我在 activity 文件中用 @EBean 注释并用 @Bean 声明。构造函数只带Context参数,其他参数的初始化我放在一个单独的方法里。

所以我认为设置满足androidannotation的要求,如果网络操作在后台进行,为什么会出现这个错误?

我要扩展的class:

@EBean
public class MomentViewAdapter extends BaseAdapter {
    protected LayoutInflater mInflater;
    protected Context mContext;
    protected List<FavoriteInfo> mDatas;
    protected  int mItemLayoutId;

    public MomentViewAdapter(Context context) {
        this.mContext = context;
//        this.mInflater = LayoutInflater.from(mContext);
//        this.mDatas = mDatas;
//        this.mItemLayoutId = itemLayoutId;
    }

    public void setUp(List<FavoriteInfo> mDatas, int itemLayoutId) {
        this.mInflater = LayoutInflater.from(mContext);
        this.mDatas = mDatas;
        this.mItemLayoutId = itemLayoutId;
    }


    @Override
    public int getCount()
    {
        return mDatas.size();
    }

    @Override
    public FavoriteInfo getItem(int position)
    {
        return mDatas.get(position);
    }

    @Override
    public long getItemId(int position)
    {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        if(convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(mItemLayoutId, parent, false);
        }
        ImageView img = (ImageView) convertView.findViewById(R.id.detail_moment_camera_picture);
        if (mDatas.get(position).isVideoFavorite()) {
            Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(mDatas.get(position).getVideoURL(), MediaStore.Video.Thumbnails.MINI_KIND);
            img.setImageBitmap(bitmap);
        } else {
            getBitmapFromURL(mDatas.get(position).getImageURL(), img);
            // img.setImageBitmap(getBitmapFromURL(mDatas.get(position).getImageURL()));
        }
        img.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(mContext, GeneratedClassUtils.get(MomentDetailActivity.class));
                Bundle mBundle = new Bundle();
                mBundle.putSerializable(FavoriteInfo.KEY, mDatas.get(position));
                mBundle.putBoolean(CollectionInfo.KEY_WATCH_FLAG, false);
                intent.putExtras(mBundle);
                mContext.startActivity(intent);
            }
        });

        return convertView;

    }

StackTrace(错误在 MomentViewAdapter 中):

09-02 11:35:17.302  30956-30956/com.bloomsky.bloomsky E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.bloomsky.bloomsky, PID: 30956
    android.os.NetworkOnMainThreadException
            at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)
            at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:249)
            at libcore.io.IoBridge.recvfrom(IoBridge.java:553)
            at java.net.PlainSocketImpl.read(PlainSocketImpl.java:485)
            at java.net.PlainSocketImpl.access[=13=]0(PlainSocketImpl.java:37)
            at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
            at com.android.okio.Okio.read(Okio.java:113)
            at com.android.okio.RealBufferedSource.indexOf(RealBufferedSource.java:147)
            at com.android.okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:94)
            at com.android.okhttp.internal.http.HttpConnection.readResponse(HttpConnection.java:175)
            at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:101)
            at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:616)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:379)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:323)
            at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:190)
            at com.bloomsky.android.ui.adapter.MomentViewAdapter.getBitmapFromURL(MomentViewAdapter.java:132)
            at com.bloomsky.android.ui.adapter.MomentViewAdapter.getView(MomentViewAdapter.java:85)
            at android.widget.AbsListView.obtainView(AbsListView.java:2346)
            at android.widget.GridView.makeAndAddView(GridView.java:1433)
            at android.widget.GridView.makeRow(GridView.java:361)
            at android.widget.GridView.fillDown(GridView.java:302)
            at android.widget.GridView.fillFromTop(GridView.java:437)
            at android.widget.GridView.layoutChildren(GridView.java:1276)
            at android.widget.AbsListView.onLayout(AbsListView.java:2150)
            at android.view.View.layout(View.java:15604)
            at android.view.ViewGroup.layout(ViewGroup.java:4967)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
            at android.view.View.layout(View.java:15604)
            at android.view.ViewGroup.layout(ViewGroup.java:4967)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
            at android.widget.ScrollView.onLayout(ScrollView.java:1502)
            at android.view.View.layout(View.java:15604)
            at android.view.ViewGroup.layout(ViewGroup.java:4967)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
            at android.view.View.layout(View.java:15604)
            at android.view.ViewGroup.layout(ViewGroup.java:4967)
            at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1703)
            at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1557)
            at android.widget.LinearLayout.onLayout(LinearLayout.java:1466)
            at android.view.View.layout(View.java:15604)
            at android.view.ViewGroup.layout(ViewGroup.java:4967)
            at in.srain.cube.views.ptr.PtrFrameLayout.layoutChildren(PtrFrameLayout.java:247)
            at in.srain.cube.views.ptr.PtrFrameLayout.onLayout(PtrFrameLayout.java:216)
            at android.view.View.layout(View.java:15604)
            at android.view.ViewGroup.layout(ViewGroup.java:4967)
            at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1077)
            at android.view.View.layout(View.java:15604)
            at android.view.ViewGroup.layout(ViewGroup.java:4967)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
            at com.bloomsky.android.ui.SwipeBackLayout.onLayout(SwipeBackLayout.java:233)
            at android.view.View.layout(View.java:15604)
            at android.view.ViewGroup.layout(ViewGroup.java:4967)
            at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
            at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
            at android.view.View.layout(View.java:15604

根据要求,这里是相关的 activity 代码:

        @Bean
        MomentViewAdapter mGridViewAdapter;mGridViewAdapter = new MomentViewAdapter(this);
        mGridViewAdapter.setUp(mMomentDatas, R.layout.device_detail_moment_listitem_simple);
        mGridView.setAdapter(mGridViewAdapter);

尝试这样做

    ImageView imageView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        imageView = (ImageView) findViewById(R.id.imageView);

        // Create an object for subclass of AsyncTask
        BitmapDownloaderTask task = new BitmapDownloaderTask();
         .
         .
         .        

    }

class BitmapDownloaderTask extends AsyncTask<String, Void, Bitmap> {
.
.
.

@Override
// Actual download method, run in the task thread
protected Bitmap doInBackground(String... params) {
     return getBitmapFromURL(params...);
}

@Override
// Once the image is downloaded, associates it to the imageView
protected void onPostExecute(Bitmap bitmap) {
    if (isCancelled()) {
        bitmap = null;
    }
        if (imageView != null) {
            imageView.setImageBitmap(bitmap);
        }
 }
}


protected void getBitmapFromURL(String src) {
        try {
            URL url = new URL(src);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();

            //New Line added
            final Bitmap bitmap = BitmapFactory.decodeStream(input);

            //return bitmap
            return bitmap;
        } catch (IOException e) {
            System.out.println("************** network exception: download image failed");
            return;
        }
    }

但是我建议您使用 Volley.

而不是这样做

这里的问题是您没有使用生成的 class,而是使用您的带注释的,当然不包含任何增强功能。您必须创建增强型适配器或将其注入到要使用它的 class 中,然后在该实例上调用后台方法。

@EActivity
public class YourActivity {

  @Bean // will inject instance of generated MomentViewAdapter_
  MomentViewAdapter adapter;

  @AfterInject // injected beans are only available from here
  public void afterInject() {
     yourList.setAdapter(adapter);
  }
}