I have a fragment as part of a bottom navigation. Inside the fragment, I have a button to select an image and show in recyclerview.
I am handling the click event of this button from onBindViewHolder()
of recyclerview by calling the method in the fragment class like this:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof TrendingHeaderViewHolder){
((TrendingHeaderViewHolder) holder).cameraShareIV.setOnClickListener( view -> {
TrendingFragment.newInstance().selectImage(); // this method is created in fragment class but called here in adapter
});
} else if (holder instanceof TrendingItemsViewHolder){
TestTrends tre = trendsList.get(position - 1);
Picasso.with(context)
.load(tre.getTestImage())
.placeholder(R.drawable.default_profile_photo)
.into(((TrendingItemsViewHolder) holder).testImgView);
}
}
and in fragment, the method is like below:
public void selectImage() {
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, GAL_REQ_CODE);
//context.startActivityForResult(intent, GAL_REQ_CODE); // tried with Activity and Context but still crashes
}
The app crashes whenever the button is clicked. Here's the error in logcat:
java.lang.IllegalStateException: Fragment TrendingFragment{171d0a0} not attached to Activity
at android.support.v4.app.Fragment.startActivityForResult(Fragment.java:1026)
at android.support.v4.app.Fragment.startActivityForResult(Fragment.java:1017)
at base.android.com.thumbsapp.UI.Fragments.TrendingFragment.selectImage(TrendingFragment.java:120)
at base.android.com.thumbsapp.Adapters.TrendingAdapter.lambda$onBindViewHolder$0$TrendingAdapter(TrendingAdapter.java:59)
at base.android.com.thumbsapp.Adapters.TrendingAdapter$$Lambda$0.onClick(Unknown Source)
at android.view.View.performClick(View.java:5690)
at android.view.View$PerformClick.run(View.java:22693)
at android.os.Handler.handleCallback(Handler.java:836)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6269)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
Here's my activity where the bottom nav fragments are inlfated:
private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= item -> {
FragmentTransaction ft = null;
switch (item.getItemId()) {
case R.id.navigation_home:
viewpager.setCurrentItem(0);
ft = getSupportFragmentManager().beginTransaction()
.replace(R.id.fragContainer, new HomeFragment());
ft.commit();
return true;
case R.id.navigation_trending:
ft = getSupportFragmentManager().beginTransaction()
.replace(R.id.fragContainer, new TrendingFragment());
ft.commit();
viewpager.setCurrentItem(2);
return true;
case R.id.navigation_chats:
ft = getSupportFragmentManager().beginTransaction()
.replace(R.id.fragContainer, new ChatsFragment());
ft.commit();
viewpager.setCurrentItem(3);
return true;
case R.id.navigation_profile:
ft = getSupportFragmentManager().beginTransaction()
.replace(R.id.fragContainer, new ProfileFragment());
ft.commit();
viewpager.setCurrentItem(4);
return true;
case R.id.navigation_search:
ft = getSupportFragmentManager().beginTransaction()
.replace(R.id.fragContainer, new SearchFragment());
ft.commit();
viewpager.setCurrentItem(1);
return true;
}
return false;
};
and the layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="base.android.com.thumbsapp.UI.Activities.MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/fragments"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_above="@+id/navigation"/>
<FrameLayout
android:id="@+id/fragContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_above="@+id/navigation"/>
<android.support.design.widget.BottomNavigationView
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
app:itemBackground="@android:color/white"
app:itemIconTint="@color/nav_bar_behave"
app:itemTextColor="@color/nav_bar_behave"
app:menu="@menu/navigation"
android:layout_alignParentBottom="true"/>
Can someone explain why the app is crashing pls?
Why is the app crashing? Because your fragment is not attached to any activity.
You should rather implement a listener in your fragment to call from your viewHolder on click event.
Inside your adapter class, define an interface
public interface OnItemClickListener {
void onItemClick();
}
while initializing your adapter class with listener implementation
public Adapter(OnItemClickListenerener listener){
this.listener = listener;
}
inside your view-holder:
viewHolder.itemView..setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listener.onItemClick();}
}
finally, implement this interface in your enclosing activity and then get your fragment to call the required method.
Also, you should move your onItemClick listener event code to view-holder from onBindViewHolder