J Freebird
J Freebird

Reputation: 3910

Android NetworkOnMainThreadException in Background Methods

I have some network requests in my app, and whenever the network related code is called, I got this exception. I already put them in background:

    @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;
    }

But the error still exists. I'm implementing my own adapter here, which extends BaseAdapter. I annotated it with @EBean and declared with @Bean in my activity file. The constructor only takes Context parameter, I put the initialization of other parameters in a separate method.

So I think the setup satisfies the requirements of androidannotation, and if the network operations are done in the background, why should this error occur?

The class I'm extending:

@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 (error is in 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$000(PlainSocketImpl.java:37)
            at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:237)
            at com.android.okio.Okio$2.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

And as requested, here is the related activity code:

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

Upvotes: 4

Views: 364

Answers (2)

WonderCsabo
WonderCsabo

Reputation: 12207

The problem here is you are not using the generated class, but your annotated one which of course does not contain any enhancements. You have to create or inject your enhanced adapter to the class where you want to use it, then call the background method on that instance.

@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);
  }
}

Upvotes: 2

Jorge Casariego
Jorge Casariego

Reputation: 22212

Try to do it this way

    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;
        }
    }

But instead of doing in this way I would recommend you the use of Volley.

Upvotes: 2

Related Questions