更新 GridView 触发器 android.os.NetworkOnMainThreadException
Updating a GridView triggers android.os.NetworkOnMainThreadException
我遇到的问题是,每次我想更新我的片段中的 gridview 时,我都会收到此错误:
android.os.NetworkOnMainThreadException
我想达到什么目标?
在我的布局中显示加载 gif,直到我的片段在后台从 firestore 加载列表,然后将数据设置到 gridview 适配器,然后隐藏加载 gif 并显示 gridview。
我已经尝试了什么?
我尝试获取数据并在 AsynkTask 和后台线程中设置适配器,但我仍然收到相同的错误。 (Firestore 本身也是异步的)
什么时候触发错误?
public void updateAdapterView(JSONArray cards) {
//Error gets triggered here
grid.invalidateViews();
adapter.refresh(cards);
}
片段Activity:
//Set Layout for Fragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final FrameLayout view = (FrameLayout) inflater.inflate(R.layout.fragment_exchange, container, false);
loadinglayout = view.findViewById(R.id.loadinglayout);
gridlayout = view.findViewById(R.id.gridlayout);
//first time setting Adapter with empty items
adapter = new ExchangeListAdapter(getContext(), cards);
grid = view.findViewById(R.id.grid);
grid.setAdapter(adapter);
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent exchangedetail = new Intent(getActivity(), ExchangeDetail.class);
//exchangedetail.putExtra("item", cardslist[+ position]);
getActivity().startActivity(exchangedetail);
}
});
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//get data from firestore
((MainActivity) getActivity()).getCardsList(new BaseAppCompatActivity.OnCardsFilledListener() {
@Override
public void onCardsFilled(final JSONArray cards) {
updateAdapterView(cards);
}
@Override
public void onError(Exception taskException) {
}
});
}
public void updateAdapterView(JSONArray cards) {
grid.invalidateViews();
adapter.refresh(cards);
}
网格视图适配器:
public class ExchangeListAdapter extends BaseAdapter {
private Context mContext;
private JSONArray cards;
public ExchangeListAdapter(Context c, JSONArray cards) {
mContext = c;
this.cards = cards;
}
@Override
public int getCount() {
int length = 0;
if(cards != null) {
length = cards.length();
}
return length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public void refresh(JSONArray cards)
{
this.cards = cards;
notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View grid;
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.item_exchange_list, null);
ImageView imageView = grid.findViewById(R.id.grid_image);
URL url = null;
try {
url = new URL(cards.getJSONObject(position).getString("thumbnail"));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
Bitmap bmp = null;
try {
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
imageView.setImageBitmap(bmp);
} else {
grid = convertView;
}
return grid;
}
}
您正在尝试从 getView()
方法中的主应用程序线程上的 URL 加载图像。
向您的项目添加 image-loading 库,例如 Glide 或 Picasso。然后,使用该库加载图像。像这样的图书馆可以:
- 处理加载状态的占位符图像
- 在后台线程上执行网络 I/O
- 缩放图像以适合您的
ImageView
同时占用更少的内存
- 处理
ImageView
回收,如果用户在图像仍在加载时滚动
我遇到的问题是,每次我想更新我的片段中的 gridview 时,我都会收到此错误:
android.os.NetworkOnMainThreadException
我想达到什么目标?
在我的布局中显示加载 gif,直到我的片段在后台从 firestore 加载列表,然后将数据设置到 gridview 适配器,然后隐藏加载 gif 并显示 gridview。
我已经尝试了什么?
我尝试获取数据并在 AsynkTask 和后台线程中设置适配器,但我仍然收到相同的错误。 (Firestore 本身也是异步的)
什么时候触发错误?
public void updateAdapterView(JSONArray cards) {
//Error gets triggered here
grid.invalidateViews();
adapter.refresh(cards);
}
片段Activity:
//Set Layout for Fragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final FrameLayout view = (FrameLayout) inflater.inflate(R.layout.fragment_exchange, container, false);
loadinglayout = view.findViewById(R.id.loadinglayout);
gridlayout = view.findViewById(R.id.gridlayout);
//first time setting Adapter with empty items
adapter = new ExchangeListAdapter(getContext(), cards);
grid = view.findViewById(R.id.grid);
grid.setAdapter(adapter);
grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent exchangedetail = new Intent(getActivity(), ExchangeDetail.class);
//exchangedetail.putExtra("item", cardslist[+ position]);
getActivity().startActivity(exchangedetail);
}
});
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//get data from firestore
((MainActivity) getActivity()).getCardsList(new BaseAppCompatActivity.OnCardsFilledListener() {
@Override
public void onCardsFilled(final JSONArray cards) {
updateAdapterView(cards);
}
@Override
public void onError(Exception taskException) {
}
});
}
public void updateAdapterView(JSONArray cards) {
grid.invalidateViews();
adapter.refresh(cards);
}
网格视图适配器:
public class ExchangeListAdapter extends BaseAdapter {
private Context mContext;
private JSONArray cards;
public ExchangeListAdapter(Context c, JSONArray cards) {
mContext = c;
this.cards = cards;
}
@Override
public int getCount() {
int length = 0;
if(cards != null) {
length = cards.length();
}
return length;
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
public void refresh(JSONArray cards)
{
this.cards = cards;
notifyDataSetChanged();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View grid;
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null) {
grid = new View(mContext);
grid = inflater.inflate(R.layout.item_exchange_list, null);
ImageView imageView = grid.findViewById(R.id.grid_image);
URL url = null;
try {
url = new URL(cards.getJSONObject(position).getString("thumbnail"));
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
Bitmap bmp = null;
try {
bmp = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
imageView.setImageBitmap(bmp);
} else {
grid = convertView;
}
return grid;
}
}
您正在尝试从 getView()
方法中的主应用程序线程上的 URL 加载图像。
向您的项目添加 image-loading 库,例如 Glide 或 Picasso。然后,使用该库加载图像。像这样的图书馆可以:
- 处理加载状态的占位符图像
- 在后台线程上执行网络 I/O
- 缩放图像以适合您的
ImageView
同时占用更少的内存 - 处理
ImageView
回收,如果用户在图像仍在加载时滚动