4

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);
J Freebird
  • 3,664
  • 7
  • 46
  • 81

2 Answers2

2

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.

Jorge Casariego
  • 21,948
  • 6
  • 90
  • 97
2

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);
  }
}
WonderCsabo
  • 11,947
  • 13
  • 63
  • 105
  • I got: Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.GridView.setAdapter(android.widget.ListAdapter)' on a null object reference at com.bloomsky.android.activities.common.DeviceDetailActivity.afterInject(DeviceDetailActivity.java:626) – J Freebird Sep 02 '15 at 21:02
  • so it says 'adapter' is null. But I did use: @AfterInject // injected beans are only available from here public void afterInject() { mGridViewAdapter.setUp(mMomentDatas, R.layout.device_detail_moment_listitem_simple); mGridView.setAdapter(mGridViewAdapter); } and annotated it with \@Bean – J Freebird Sep 02 '15 at 21:03
  • Actually I've used EBean for some time, but I never used the AfterInject annotation. All my previous codes run perfect without it. I thought the instance is automatically created once you used @Bean – J Freebird Sep 02 '15 at 21:05
  • The NPE: if you inject the `GridView`, you have to use `@AfterViews`, instead of `@AfterInject.` – WonderCsabo Sep 02 '15 at 22:18
  • Of course an instance is not created. You have to inject an instance, like i said. But you also created an instance, i guess you just used `new MomentViewAdapter()`, which created an instance of the not-enhanced class.. – WonderCsabo Sep 02 '15 at 22:20
  • Sorry, that is old cold. I didn't have new MomentViewAdapter(). Actually the method with \@AfterInject is called inside another method with \@AfterViews. – J Freebird Sep 02 '15 at 23:11
  • But the setUp method of that instance did not throw any errors, although it is called before setAdapter, which is confusing to me. – J Freebird Sep 02 '15 at 23:13
  • The mGridView field is null, when you call setAdapter on it, that is the problem. This means you forgot to instantiate that field, or you use it too early. – WonderCsabo Sep 03 '15 at 05:43
  • Yes, when I deleted @afterInject, it worked. I think this decorator injects both the views and the enhanced classes. Thanks. – J Freebird Sep 03 '15 at 16:59
  • Yes. In `@AfterInject` annotated methods injected prefs, resources, beans are available. In `@AfterViews` annotated methods, also views are available. – WonderCsabo Sep 03 '15 at 17:04