I'm pretty new at Android, so I've already seen similar questions like mine, but I still can't send a Text to another fragment. I get this following error:
java.lang.NullPointerException: Attempt to invoke virtual method '
Here's the code, for better understanding...
FragOne
public class FragOne extends Fragment {
SendDados enviar;
String NumPessoas;
public interface SendDados{
void setdados(String numPessoas);
}
#Override
public void onAttach(Activity activity){
super.onAttach(activity);
try{ enviar=(SendDados)activity;
}catch (ClassCastException e){
throw new ClassCastException("erro");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.reserva_layout, container, false);
final TextView numero=(TextView)rootView.findViewById(R.id.qtdPessoas);
reservar.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NumPessoas= numero.getText().toString();
enviar.setdados("1");
}
});
FragTwo
public class FragTwo extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.confirm_reserva_layout, container, false);
numeroPessoas=(TextView)rootView.findViewById(R.id.numPessoas);
return rootView;
}
public void UpdateDados(String numPessoas)
{
numeroPessoas.setText(numPessoas);
}
Activity
public class MenuActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener,ReservaFragment.SendDados {
#Override
public void setdados(String numPessoas) {
ConfirmaReservaFragment cf= (ConfirmaReservaFragment)getSupportFragmentManager().findFragmentById(R.id.confirmaReserva);
cf.UpdateDados(numPessoas);
}
What I need to do is this, when I click the button, the textView from FragOne, must be copied to FragTwo, what am I doing wrong here? I always get this error:
java.lang.NullPointerException: Attempt to invoke virtual method '
I appreciate any help.
Since we are talking about simple TextViews, copying the whole TextView to send it to another fragment seems too complicated for a simple job. Just send a String and display the text inside a new TextView inside FragTwo.
I recommend reading this link for passing parameters to fragments before their construction.
If you insist on passing TextViews as parameters to fragments then you are going to have to find a way to serialize TextViews (I don't think they implement Parcelable) and that won't be a simple job.
Regarding your code:
Names of objects start with small caps (first snippet).
Names of methods start with small caps (last snippet).
Use instanceof in onAttach (first snippet).
I don't see what ConfirmaReservaFragment is?
Also I really really recommend you type your code in English.
Fragments should comunicate through an activity so i will post you a short example of how to correctly send data from one fragment to another using a host activity:
First we will use this layout named host activity layout with a framelayout as a parent called host_fragment_container :
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/host_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
now we are going to load our host activity and set this layout as a content view and create a basic method to change fragments on this frame layout :
public class HostActivity extends AppCompatActivity
implements TextViewContainerFragment.textViewClickListener{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.host_activity_layout);
}
private void switchFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.host_fragment_container, fragment)
.commit();
}
}
Now lets create our first fragment (the one who will send the text) :
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:id="#+id/text_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
we will use this same xml file for both sender and receiver fragments
public class TextViewContainerFragment extends Fragment {
public interface textViewClickListener {
void onTextViewClicked(String value);
}
private textViewClickListener mActivityCallback;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.text_view_container_fragment, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final TextView textView = (TextView) view.findViewById(R.id.text_view);
//search the view by id and cast it into a text view the set it on click lsitener
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// now if the cast was successful the activity callback will be valid and ready to use
// but we are going to check if its valid anyways
if (mActivityCallback != null) {
mActivityCallback.onTextViewClicked(textView.getText().toString());
}
}
});
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
// if context is extracted from an activity
// that means its safe to cast
if (context instanceof Activity) {
mActivityCallback =
(textViewClickListener) context;
}
}
// factory method
public static TextViewContainerFragment newInstance() {
return new TextViewContainerFragment();
}
}
now that we have our interface on the fragment we will implement it on the host activity to listen for callbacks & its going to call a sencond fragment ot display the sent text :
public class HostActivity extends AppCompatActivity
implements TextViewContainerFragment.textViewClickListener{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.host_activity_layout);
if (savedInstanceState == null) {
switchFragment(TextViewContainerFragment.newInstance());
}
}
private void switchFragment(Fragment fragment) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.host_fragment_container, fragment)
.commit();
}
#Override
public void onTextViewClicked(String value) {
switchFragment(TextReceiverFragment.newInstance(value));
}
}
Here is the code for the receiver fragment (older fragment will be replaced for this one) :
public class TextReceiverFragment extends Fragment {
public static final String ARG_TEXT_RECEIVED_FROM_ANOTHER_FRAGMENT = "text";
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.text_view_container_fragment, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((TextView) view.findViewById(R.id.text_view)).setText(getArguments() != null ?
getArguments().getString(ARG_TEXT_RECEIVED_FROM_ANOTHER_FRAGMENT)
: "No text was sent from another fragment");
}
public static TextReceiverFragment newInstance(String text) {
TextReceiverFragment fragment = new TextReceiverFragment();
Bundle argument = new Bundle();
argument.putString(ARG_TEXT_RECEIVED_FROM_ANOTHER_FRAGMENT,
text);
fragment.setArguments(argument);
return fragment;
}
}
If you really want to copy the textview from Fragment 1 to Fragment 2. I suggested you to send the config data (e.g. the text, clicked, color) of the textview instead of the whole object. As the response from Spidey ,sending the widget to other fragment will be a trouble.
To facilitate your work, A textview config model should be used to send the config data of the textview.
public class TextViewConfig implements Parcelable {
private String text;
private boolean selected;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.text);
dest.writeByte(this.selected ? (byte) 1 : (byte) 0);
}
public TextViewConfig() {
}
protected TextViewConfig(Parcel in) {
this.text = in.readString();
this.selected = in.readByte() != 0;
}
public static final Parcelable.Creator<TextViewConfig> CREATOR = new Parcelable.Creator<TextViewConfig>() {
#Override
public TextViewConfig createFromParcel(Parcel source) {
return new TextViewConfig(source);
}
#Override
public TextViewConfig[] newArray(int size) {
return new TextViewConfig[size];
}
};
public String getText() {
return text;
}
public void setText(String pText) {
text = pText;
}
public boolean isSelected() {
return selected;
}
public void setSelected(boolean pSelected) {
selected = pSelected;
}
}
Since the model class can be implemented as Parcelable easily, you can use it to send the data of the textview. And then you can use the answer from Juan Hurtado to practice the communication between the fragments by sending the config data.
let's supose u wants to got to the fragment two from fragment one with text "hello" by a click event on fragment one,
your code look like this,
class FragOne extends Fragment{
onCreateView(){
.
.
<your view>.setOnClickListener(new OnClickListener(){
#cverride
onClick(){
Bundle bundle=new Bundle();
bundle.putString("msg","<ur text will gose here which u wants to send to fragment two>");
.
.
.
//now move to the fragment two here
FragTwo fragTwo=new FragTwo();
fragTwo.setArgument(bundle);
FragmentManager fragmentManager=getSupportFragmentManager();
fragmentManager.beginTransaction().add(<ur root layout is>,fragmentTwo).commit();
}
});
}
}
Now in ur Fragmnet Two,
class FragTwo extends Fragment{
onCreateView(){
.
.
//get text which is send by fragment one
Bundle bundle=new Bundle();
String text=bundle.getString("msg");//this is ur text which is send by fragment one
}
}
Hope this will help u,
Related
When I go to click an item in the SettingsFragment, my app crashes. Everything is displayed properly in this fragment class but only my parseUrl items work. i click on any other items and my app just closes out. Why does that happen? Below is my code.
public class SettingsFragment extends Fragment {
MainActivity context;
public SettingsFragment() {
//public constructor
}
#NonNull
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.navigation_drawer, container, false);
FrameLayout instructions = view.findViewById(R.id.instructions);
if (!getInstance().get("INSTRUCTIONS_ACTIVE", true)) {
instructions.setVisibility(View.GONE);
}
instructions.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
openInstructions();
}
});
return view;
}
// Main functions
void openInstructions(){
Intent transactions = new Intent(context, FragmentsActivity.class);
transactions.putExtra("show","instructions");
startActivity(transactions);
}
public void settingsMenu(String Type){
switch (Type) {
case "instructions":
openInstructions();
break;
}
It seems that the context is null
Use getContext() or getActivity() inside onCreateView to initialize the context
context is not initialized, one way to do that is to add this method:
#Override
public void onAttach(Context ctx) {
super.onAttach(ctx);
context = ctx;
}
I'm testing a function of listening the AlertDialog button click (Positive & Neutral) in each ViewPager fragment. And I am using the Interface method right now but getting some troubles.
So the structure is like this, I have an AlertDialog created by DialogFragment, and I put a ViewPager with two fragments into this DialogFragment. My goal is, when I click on the Positive button on the AlertDialog, I want some methods inside those two ViewPager fragments get called so that I can collect the data on those fragments.
Now the problem is, only the second fragment responses, I don't know why.
Here are the codes:
I created an Interface file
public interface Communicator {
void onConfirmClick();
}
I have a DialogFragment
public class MainDialogFragment extends DialogFragment {
View dialogLayout;
Communicator communicator;
#Override
public void onAttachFragment(Fragment childFragment) {
communicator = (Communicator) childFragment;
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return dialogLayout;
}
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getActivity());
dialogLayout = getActivity().getLayoutInflater().inflate(R.layout.dialog_main, null);
ViewPager viewPager = dialogLayout.findViewById(R.id.main_viewPager);
final MainPagerAdapter adapter = new MainPagerAdapter(getChildFragmentManager());
viewPager.setAdapter(adapter);
dialogBuilder.setView(dialogLayout);
dialogBuilder.setPositiveButton("Confirm", null);
dialogBuilder.setNegativeButton("Cancel", null);
dialogBuilder.setNeutralButton("Change", null);
final AlertDialog dialog = dialogBuilder.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialogInterface) {
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
communicator.onConfirmClick();
}
});
dialog.getButton(DialogInterface.BUTTON_NEUTRAL).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "Change click!!", Toast.LENGTH_SHORT).show();
}
});
}
});
return dialog;
}
}
My fragment A
public class MainFragmentA extends Fragment implements Communicator{
View rootView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_a, container, false);
return rootView;
}
#Override
public void onConfirmClick() {
Toast.makeText(getContext(), "Fragment A!!", Toast.LENGTH_SHORT).show();
}
}
My fragment B
public class MainFragmentB extends Fragment implements Communicator{
View rootView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_b, container, false);
return rootView;
}
#Override
public void onConfirmClick() {
Toast.makeText(getContext(), "Fragment B!!", Toast.LENGTH_SHORT).show();
}
}
My ViewPager adapter used inside DialogFragment
public class MainPagerAdapter extends FragmentPagerAdapter {
public MainPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new MainFragmentA();
case 1:
return new MainFragmentB();
default:
throw new IllegalArgumentException("Wrong position!!");
}
}
#Override
public int getCount() {
return 2;
}
}
My MainActivity
public class MainActivity extends AppCompatActivity{
Button showDialogButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showDialogButton = findViewById(R.id.main_show_dialog_button);
showDialogButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
MainDialogFragment mainDialogFragment = new MainDialogFragment();
mainDialogFragment.show(getSupportFragmentManager(), "mainDialogFragment");
}
});
}
}
Anyone can help? I'll so appreciate that!!!
Use a collection of some sort of Communicator interfaces instead of a single one. You're overwriting the communicator every time a child fragment is attached.
public class MainDialogFragment extends DialogFragment {
View dialogLayout;
List<Communicator> communicators = new ArrayList<>();
#Override
public void onAttachFragment(Fragment childFragment) {
communicators.add((Communicator) childFragment);
}
// all the other things from the MainDialogFragment...
}
And in the BUTTON_POSITIVE callback iterate through the list.
dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
for (Communicator communicator : communicators) {
communicator.onConfirmClick();
}
}
});
Only the communicator from the second fragment works
This is because you have two different instances of communicator in each of your fragments. As you are setting up the ViewPager, the second fragment is the last one that is being attached with the parent fragment. Hence, the communicator that you are initializing inside the onAttachFragment function of your MainDialogFragment class, is storing the reference from the second fragment only as this was the last one to be attached here.
In your case, I would rather suggest a very simple implementation using the lifecycle functions of the Fragment. Just take a public static variable in your MainDialogFragment class which will indicate if the okay button was clicked or not. And then check the value of that variable from each of your Fragment class inside the onResume function and perform the tasks accordingly. To get an idea of the implementation, please check the following.
Get a variable in your MainDialogFragment class like the following.
public static boolean isDialogOkayClicked = false; // Default false
Now in your MainFragmentA, implement the onResume function and check the value from the MainDialogFragment. Take the actions accordingly.
public class MainFragmentA extends Fragment implements Communicator{
View rootView;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_a, container, false);
return rootView;
}
#Override
protected void onResume() {
super.onResume();
if(MainDialogFragment.isDialogOkayClicked)
doSomething();
}
#Override
public void onConfirmClick() {
Toast.makeText(getContext(), "Fragment A!!", Toast.LENGTH_SHORT).show();
}
}
Do the same thing for your other fragment.
Hope that helps!
I have Fragments with a play button in my fragment. Whenever the user presses the play button from the ViewPager fragment, it calls a function in host activity which plays the player.
I am trying to implement the live data by using a ViewModel but unsuccessful.
public class SlidePlayerFragment extends Fragment {
private MyViewModel viewModel;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View view = inflater.inflate(R.layout.fragment_slide_player, container, false);
ImageView playBtn = view.findViewById(R.id.playBtn);
playBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewModel.getIsPlaying().setValue(true);
viewModel.getCheck().setValue("Checking");
}
});
return view;
}
}
}
Here's my PagerAdapter
public class MyViewPagerAdapter extends FragmentStatePagerAdapter {
private int pages;
public MyViewPagerAdapter(FragmentManager fm,int count) {
super(fm);
pages = count;
}
#Override
public Fragment getItem(int i) {
return new SlidePlayerFragment();
}
#Override
public int getCount() {
return pages;
}
}
Here is the view model function
private MutableLiveData<Boolean> isPlaying;
public MutableLiveData<Boolean> getIsPlaying() {
if (isPlaying == null)
isPlaying = new MutableLiveData<>();
Log.d("TAG","Checking "+isPlaying.getValue());
return isPlaying;
}
And here is the observer segment
final Observer<Boolean> isPlaying= isPlaying -> {
//code here if playing then do some task here
};
viewModel.getIsPlaying().observe(this,isPlaying);
Note I already tried to find the predefined solution but I didn't find anything.
You do not really have to have a ViewModel for this purpose. You might just consider having public functions in the Activity which hosts the Fragments. For example, let us consider you have the following public functions in your PlayerActivity which launches all the other fragments.
public void play(String songName) {
viewModel.getIsPlaying().setValue(true);
viewModel.getCheck().setValue("Checking");
// Other actions for playing
}
Now, you might just consider the following onClick function instead of the one you are having now.
playBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((PlayerActivity) getActivity()).play(songName);
}
});
Hope that helps!
Sorry for my english. I have one activity and in this activity in FragmentPagerAdapter exist 5 fragments. All fragments use one object model for inforation(product name, product image ...).
My activity get data from data base. And then it data send to all fragments. My example Activity:
#BindView(R.id.tabs_sep_prod) TabLayout tabs_sep_prod;
#BindView(R.id.viewpager_sep_prod) ViewPager viewpager_sep_prod;
PrepBaseProdFragment prepBaseProdFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sep_product);
ButterKnife.bind(this);
prepBaseProdFragment = new PrepBaseProdFragment();
// there i have another fragments
// ...
setupViewPager(viewpager_sep_prod);
tabs_sep_prod.setupWithViewPager(viewpager_sep_prod);
}
private void setupViewPager(ViewPager viewPager) {
SepProductActivity.ViewPagerAdapter adapter = new SepProductActivity.ViewPagerAdapter(
adapter.addFrag(prepBaseProdFragment, getString(R.string.sep_prep_base));
// there i have another addFrag
// ...
viewPager.setOffscreenPageLimit(5);
viewPager.setAdapter(adapter);
}
#Override
public void onResume() {
super.onResume();
// this i call method from presenter, it return data in method setData
if(idCat != null && idProd != null)
sepProductPresenter.getSepProd(idCat, idProd);
}
#Override
public void setData(SepProductModel sepProductModel) {
// there i send data to fragment
prepBaseProdFragment.setDataInf(sepProductModel);
// ...
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
my fragment
public class PrepBaseProdFragment extends BaseFragment {
#BindView(R.id.text) TextView text;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_about_prod_prepare_base, parent, false);
ButterKnife.bind(this, view);
Log.e("PrepBaseProdFragment", "PrepBaseProdFragment");
return view;
}
public void setDataInf(SepProductModel sepProductModel) {
text.setText(sepProductModel.getPROPERTY_PR_SUBSTRPREP_UA_VALUE().getTEXT());
}
}
My question: when i send data from activity to fragment, my view do not have time to initialize. In fragment line text.setText(sepProductModel.getPROPERTY_PR_SUBSTRPREP_UA_VALUE().getTEXT()); error
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.TextView.setText(java.lang.CharSequence)' on a null
object reference
Please, help me solve my problem. I spend many times for this
You can check if the text view is null save the data in a variable inside the fragment and in onCreateView use the data variable if it is filled and set the textview text.
Something like this:
// Inside the Fragment body
private SepProductModel sepProductModel;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_about_prod_prepare_base, parent, false);
ButterKnife.bind(this, view);
Log.e("PrepBaseProdFragment", "PrepBaseProdFragment");
if(this.sepProductModel != null)
text.setText(this.sepProductModel.getPROPERTY_PR_SUBSTRPREP_UA_VALUE().getTEXT());
return view;
}
public void setDataInf(SepProductModel sepProductModel) {
if(text != null){
// use text
}
else this.sepProductModel=sepProductModel;
}
I can advise you to wait for your data and then show fragments to adapter, moreover all of them use the same model. While you dont have data, you can show progress bar.
When you have needed model, you can create instances of your fragments and set bundle arguments for them. You can use method like this:
public static MyFragment newInstance(MyModel model){
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putSerializable(KEY, model);//or args.putParcelable(KEY, model);
fragment.setArguments(args);
return fragment;
}
Notice: your model need to implement Serializable or Parcelable to be putted in bundle. You may read about difference here.
Then in your set data method, when you already have your model you can setup your adapter and set it to view pager, but with this approach:
adapter.addFrag(MyFragment.newInstance(model), getString(R.string.sep_prep_base));
It have to help you, ask me if you have some questions.
I'm trying out Otto on Android and i'm trying to send back a message from my Fragment to the Activity. Here's the basics of my code:
My Bus provider:
public final class BusProvider {
private static final Bus mInstance = new Bus();
private BusProvider() {}
public static Bus getBusProviderInstance() {
return mInstance;
}
}
My Activity has the following code:
public class MyActivity
extends BaseActivity {
// ....
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BusProvider.getBusProviderInstance().register(this);
// ....
}
#OnClick(R.id.profile_image)
public void onImageClicked() {
// ...
MyFragment fragment = MyFragment.newInstance(choices);
fragment.show(getFragmentManager(), "myChoices");
}
#Subscribe
public void onButtonChoicePicked(MyFragment.ChoicePickedEvent event) {
Toast.makeText(this, "reaching here", Toast.LENGTH_SHORT).show();
}
#Override
protected void onStop() {
super.onStop();
BusProvider.getBusProviderInstance().unregister(this);
}
// ...
}
and these are the important bits of code from my Fragment:
public class MyFragment
extends BaseDialogFragment {
// ...
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.dialog_choices,
container,
false);
setupDialogButtons(inflater, layout);
return layout;
}
private void setupDialogButtons(LayoutInflater inflater, LinearLayout parentView) {
ChoiceButtonViewHolder holder;
holder = new ChoiceButtonViewHolder(inflater, parentView);
holder.populateContent("First Choice", 1);
parentView.addView(holder.mChoiceTextView);
}
class ChoiceButtonViewHolder {
#InjectView(R.id.item_dialog_choice_desc) TextView mChoiceTextView;
private int mPosition;
ChoiceButtonViewHolder(LayoutInflater inflater, ViewGroup container) {
TextView mChoiceTextView = (TextView) inflater.inflate(R.layout.item_dialog_choice, container, false);
ButterKnife.inject(this, mChoiceTextView);
}
public void populateContent(String choiceDesc, int position) {
mChoiceTextView.setText(choiceDesc);
mPosition = position;
}
#OnClick(R.id.item_dialog_choice_desc)
public void onChoiceClicked() {
MyFragment.this.mDialog.dismiss();
BusProvider.getBusProviderInstance().post(new ChoicePickedEvent(1));
}
}
public static class ChoicePickedEvent {
public int mPositionClicked;
ChoicePickedEvent(int position) {
mPositionClicked = position;
}
}
}
I don't get any errors. But when i click my button from the fragment, the event onButtonChoicePicked doesn't get called.
Am I doing something wrong?
Am i misunderstanding how Otto works?
Is it a weird combination of ButterKnife and Otto that makes it not work?
Make sure you are importing "com.squareup.otto.Subscribe" not "com.google.common.eventbus.Subscribe"
The example code works without any issues independently. The reason i was facing this problem initially (as was rightly pointed out by #powerj1984): There was a misconfiguration in my project, where the bus that was being injected (via Dagger) was different from the bus instance that was being subscribed to for updates :P.
Lesson learnt: make sure the bus you use, is the same instance in both cases.