使用 FragmentStatePagerAdapter 更改 Fragment 中 ImageView 的图像
Changing image of ImageView in Fragment using FragmentStatePagerAdapter
我在片段中有一个 viewpager,我想在运行时修改由 viewPager 托管的片段的内容。
我想从 Firebase 获取数据并将查询结果添加到适配器。每当在 onChildAdded 上收到响应时,我都会将数据添加到我的数组列表并调用响应,其中更新适配器的数据并调用 notifyDataSetChanged。
在 FindSlideFragment 中更改图像时出现 NullPointerException,我无法弄清楚为什么布局不正确已填充或如果我遗漏了什么。
如果这不是更新我的片段的正确方法,那么什么是合适的方法?
FindFragment.java
public class FindFragment extends Fragment {
private Firebase ref;
private String name="";
private String email="";
private String pass="";
private String image="";
private String uid="";
ArrayList<Snap> snapsList = new ArrayList<>();
private ViewPager viewPager;
private ScreenSlidePagerAdapter mPagerAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.find_fragment, container, false);
Bundle bundle = getArguments();
uid = bundle.getString("uid");
email = bundle.getString("email");
pass = bundle.getString("pass");
Firebase ref = new Firebase(Constants.FIREBASE_URL+"snaps/");
Query queryRef = ref.orderByKey();
queryRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChild) {
Iterator<DataSnapshot> it = snapshot.getChildren().iterator();
Snap snap = snapshot.getValue(Snap.class);
snapsList.add(snap);
reload();
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
viewPager = (ViewPager) root.findViewById(R.id.pager);
/** Important: Must use the child FragmentManager or you will see side effects. */
mPagerAdapter= new ScreenSlidePagerAdapter(getChildFragmentManager(), snapsList.size(), getContext(), snapsList);
viewPager.setAdapter(mPagerAdapter);
return root;
}
private void reload() {
mPagerAdapter.setData(snapsList);
mPagerAdapter.setSlideCount();
mPagerAdapter.notifyDataSetChanged();
viewPager.invalidate();
//viewPager.setCurrentItem(0);
}
/**
* A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
* sequence.
*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
private int slideCount;
private Context context;
ArrayList<Snap> snapsList = new ArrayList<>();
public ScreenSlidePagerAdapter(FragmentManager fm, int slideCount, Context context, ArrayList<Snap> snaps) {
super(fm);
this.slideCount = slideCount;
this.context = context;
this.snapsList = snaps;
}
@Override
public Fragment getItem(int position) {
FindSlideFragment fragment = new FindSlideFragment();
if(!snapsList.isEmpty())
fragment.setImage(snapsList.get(position).getImage());
return fragment;
}
@Override
public int getCount() {
return slideCount;
}
public void setSlideCount(){
slideCount = snapsList.size();
}
public void setData(ArrayList<Snap> snaps) {
this.snapsList = snaps;
}
}
}
FindSlideFragment.java
public class FindSlideFragment extends Fragment {
ViewGroup rootView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = (ViewGroup) inflater.inflate(
R.layout.find_content_fragment, container, false);
return rootView;
}
public void setImage(String image) {
ImageView iv_snap = (ImageView)rootView.findViewById(R.id.imageView_snap);
byte[] imageAsBytes = Base64.decode(image, Base64.DEFAULT);
Bitmap bmp = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
iv_snap.setImageBitmap(bmp);
}
}
StackTrace
03-18 21:09:52.980 10354-10354/com.codelycan.foodtinder E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.codelycan.foodtinder, PID: 10354
java.lang.NullPointerException
at com.codelycan.foodtinder.FindSlideFragment.setImage(FindSlideFragment.java:39)
at com.codelycan.foodtinder.FindFragment$ScreenSlidePagerAdapter.getItem(FindFragment.java:156)
at android.support.v4.app.FragmentStatePagerAdapter.instantiateItem(FragmentStatePagerAdapter.java:105)
at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:943)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1091)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:608)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:570)
at android.support.v4.view.ViewPager.dataSetChanged(ViewPager.java:1019)
at android.support.v4.view.ViewPager$PagerObserver.onChanged(ViewPager.java:2989)
at android.support.v4.view.PagerAdapter.notifyDataSetChanged(PagerAdapter.java:279)
at com.codelycan.foodtinder.FindFragment.reload(FindFragment.java:129)
at com.codelycan.foodtinder.FindFragment.access[=12=]0(FindFragment.java:28)
at com.codelycan.foodtinder.FindFragment.onChildAdded(FindFragment.java:64)
at com.firebase.client.core.ChildEventRegistration.fireEvent(ChildEventRegistration.java:48)
at com.firebase.client.core.view.DataEvent.fire(DataEvent.java:45)
at com.firebase.client.core.view.EventRaiser.run(EventRaiser.java:38)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5426)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
at dalvik.system.NativeStart.main(Native Method)
试试这个:
public class FindSlideFragment extends Fragment {
ViewGroup rootView;
ImageView iv_snap;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = (ViewGroup) inflater.inflate(R.layout.find_content_fragment, container, false);
iv_snap = (ImageView)rootView.findViewById(R.id.imageView_snap);
return rootView;
}
public void setImage(String image) {
byte[] imageAsBytes = Base64.decode(image, Base64.DEFAULT);
Bitmap bmp = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
iv_snap.setImageBitmap(bmp);
}
}
我试图在填充之前更改片段的视图
@Override
public Fragment getItem(int position) {
FindSlideFragment fragment = new FindSlideFragment();
if(!snapsList.isEmpty())
fragment.setImage(snapsList.get(position).getImage());
return fragment;
}
此处片段在返回之前不会被填充,但我尝试在片段被填充之前更改图像视图,这很自然会引发空指针异常。
周转可能有多种方式,但我所做的是填充一次片段并不断更改同一片段的图像视图源。
我在片段中有一个 viewpager,我想在运行时修改由 viewPager 托管的片段的内容。
我想从 Firebase 获取数据并将查询结果添加到适配器。每当在 onChildAdded 上收到响应时,我都会将数据添加到我的数组列表并调用响应,其中更新适配器的数据并调用 notifyDataSetChanged。
在 FindSlideFragment 中更改图像时出现 NullPointerException,我无法弄清楚为什么布局不正确已填充或如果我遗漏了什么。
如果这不是更新我的片段的正确方法,那么什么是合适的方法?
FindFragment.java
public class FindFragment extends Fragment {
private Firebase ref;
private String name="";
private String email="";
private String pass="";
private String image="";
private String uid="";
ArrayList<Snap> snapsList = new ArrayList<>();
private ViewPager viewPager;
private ScreenSlidePagerAdapter mPagerAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.find_fragment, container, false);
Bundle bundle = getArguments();
uid = bundle.getString("uid");
email = bundle.getString("email");
pass = bundle.getString("pass");
Firebase ref = new Firebase(Constants.FIREBASE_URL+"snaps/");
Query queryRef = ref.orderByKey();
queryRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChild) {
Iterator<DataSnapshot> it = snapshot.getChildren().iterator();
Snap snap = snapshot.getValue(Snap.class);
snapsList.add(snap);
reload();
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
viewPager = (ViewPager) root.findViewById(R.id.pager);
/** Important: Must use the child FragmentManager or you will see side effects. */
mPagerAdapter= new ScreenSlidePagerAdapter(getChildFragmentManager(), snapsList.size(), getContext(), snapsList);
viewPager.setAdapter(mPagerAdapter);
return root;
}
private void reload() {
mPagerAdapter.setData(snapsList);
mPagerAdapter.setSlideCount();
mPagerAdapter.notifyDataSetChanged();
viewPager.invalidate();
//viewPager.setCurrentItem(0);
}
/**
* A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
* sequence.
*/
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
private int slideCount;
private Context context;
ArrayList<Snap> snapsList = new ArrayList<>();
public ScreenSlidePagerAdapter(FragmentManager fm, int slideCount, Context context, ArrayList<Snap> snaps) {
super(fm);
this.slideCount = slideCount;
this.context = context;
this.snapsList = snaps;
}
@Override
public Fragment getItem(int position) {
FindSlideFragment fragment = new FindSlideFragment();
if(!snapsList.isEmpty())
fragment.setImage(snapsList.get(position).getImage());
return fragment;
}
@Override
public int getCount() {
return slideCount;
}
public void setSlideCount(){
slideCount = snapsList.size();
}
public void setData(ArrayList<Snap> snaps) {
this.snapsList = snaps;
}
}
}
FindSlideFragment.java
public class FindSlideFragment extends Fragment {
ViewGroup rootView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = (ViewGroup) inflater.inflate(
R.layout.find_content_fragment, container, false);
return rootView;
}
public void setImage(String image) {
ImageView iv_snap = (ImageView)rootView.findViewById(R.id.imageView_snap);
byte[] imageAsBytes = Base64.decode(image, Base64.DEFAULT);
Bitmap bmp = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
iv_snap.setImageBitmap(bmp);
}
}
StackTrace
03-18 21:09:52.980 10354-10354/com.codelycan.foodtinder E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.codelycan.foodtinder, PID: 10354
java.lang.NullPointerException
at com.codelycan.foodtinder.FindSlideFragment.setImage(FindSlideFragment.java:39)
at com.codelycan.foodtinder.FindFragment$ScreenSlidePagerAdapter.getItem(FindFragment.java:156)
at android.support.v4.app.FragmentStatePagerAdapter.instantiateItem(FragmentStatePagerAdapter.java:105)
at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:943)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1091)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:608)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:570)
at android.support.v4.view.ViewPager.dataSetChanged(ViewPager.java:1019)
at android.support.v4.view.ViewPager$PagerObserver.onChanged(ViewPager.java:2989)
at android.support.v4.view.PagerAdapter.notifyDataSetChanged(PagerAdapter.java:279)
at com.codelycan.foodtinder.FindFragment.reload(FindFragment.java:129)
at com.codelycan.foodtinder.FindFragment.access[=12=]0(FindFragment.java:28)
at com.codelycan.foodtinder.FindFragment.onChildAdded(FindFragment.java:64)
at com.firebase.client.core.ChildEventRegistration.fireEvent(ChildEventRegistration.java:48)
at com.firebase.client.core.view.DataEvent.fire(DataEvent.java:45)
at com.firebase.client.core.view.EventRaiser.run(EventRaiser.java:38)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5426)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1268)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1084)
at dalvik.system.NativeStart.main(Native Method)
试试这个:
public class FindSlideFragment extends Fragment {
ViewGroup rootView;
ImageView iv_snap;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = (ViewGroup) inflater.inflate(R.layout.find_content_fragment, container, false);
iv_snap = (ImageView)rootView.findViewById(R.id.imageView_snap);
return rootView;
}
public void setImage(String image) {
byte[] imageAsBytes = Base64.decode(image, Base64.DEFAULT);
Bitmap bmp = BitmapFactory.decodeByteArray(imageAsBytes, 0, imageAsBytes.length);
iv_snap.setImageBitmap(bmp);
}
}
我试图在填充之前更改片段的视图
@Override
public Fragment getItem(int position) {
FindSlideFragment fragment = new FindSlideFragment();
if(!snapsList.isEmpty())
fragment.setImage(snapsList.get(position).getImage());
return fragment;
}
此处片段在返回之前不会被填充,但我尝试在片段被填充之前更改图像视图,这很自然会引发空指针异常。
周转可能有多种方式,但我所做的是填充一次片段并不断更改同一片段的图像视图源。