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);
}
}
我的应用程序中有一些网络请求,每当调用网络相关代码时,我都会遇到此异常。我已经把它们放在后台了:
@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);
}
}