I want to use eventbus into my app. for that I add eventbus lib to my gradle.then I have created a class like this:
public class UserEvent {
private User eUser; // esup user model
private String domain;
private String securitySrv;
private Cookie cookie;
private int totalUsersSecurity;
private ExecutorService executorService;
// constructor and getter
then into main fragment I have added this lines and finally I have posted my message:
UserEvent userEvent = new UserEvent(eUser, domain, securitySrv, cookie,
totalUsersSecurity, executorService);
EventBus.getDefault().post(userEvent);
into main fragment I have ViewPager that this pager have loaded another fragment called AllUsersFragment.
In AllUsersFragment first I have registered eventbus:
EventBus bus = EventBus.getDefault();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_layout, container, false);
bus.register(this);
return rootView;
}
and then i wrote this method:
#Subscribe
public void onEvent(UserEvent event) {
securitySrv = event.getSecuritySrv();
cookie = event.getCookie();
totalUsersSecurity = event.getTotalUsersSecurity();
executorService = event.getExecutorService();
}
into my resume method I want to pass UserEvent from eventbus to another class by its constructor:
#Override
public void onResume() {
super.onResume();
paginator = new Paginator(getContext(),totalUsersSecurity,executorService);
}
but totalUsersSecurity and executorService are null? while these variables was fill at main fragment.in debug mod at android studio this public void onEvent(UserEvent event) is not never called.
thank you for helping?
I am using android studio 3 with gradle:3.0.0'
Finally I fix this problem. according eventBus wiki
I just use Sticky Events .now I received my post
have you registered for the event on OnStart()
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
Related
I have this issue of sending some data back and forth between a fragment and its container activity, I succeeded in doing it. What puzzles me is sending my data from the fragment to the activity, at first I implemented OnResume(), OnStop() and sent the data through an intent and that created an infinite loop so I removed them. Then I did setRetainInstance(true) and it worked and gave me the wanted behavior.
My Question is How my data are really being sent and where in the fragment lifecycle ?
The Right approach is to use Interfaces. Don't use onStop or setRetainInstance()
See this. It will solve you problem.
Pass data from fragment to actvity
You can also achieve this by using Interface, using an EventBus like LocalBroadcastManager, or starting a new Activity with an Intent and some form of flag passed into its extras Bundle or something else.
Here is an example about using Interface:
1. Add function sendDataToActivity() into the interface (EventListener).
//EventListener.java
public interface EventListener {
public void sendDataToActivity(String data);
}
2. Implement this functions in your MainActivity.
// MainActivity.java
public class MainActivity extends AppCompatActivity implements EventListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public void sendDataToActivity(String data) {
Log.i("MainActivity", "sendDataToActivity: " + data);
}
}
3. Create the listener in MyFragment and attach it to the Activity.
4. Finally, call function using listener.sendDataToActivity("Hello World!").
// MyFragment.java
public class MyFragment extends Fragment {
private EventListener listener;
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
if(activity instanceof EventListener) {
listener = (EventListener)activity;
} else {
// Throw an error!
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my, container, false);
// Send data
listener.sendDataToActivity("Hello World!");
return view;
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
}
Hope this will help~
I'm trying to pass data between a fragment and an activity and I can't. I get no errors or exceptions. On my fragment I have the vallue and on activity that value is null. I'm using interfaces.
Code of HoroscopeChoice Fragment, which is the fragment with buttons. Each button has a value, which I want to pass to the activity every time I push them.
(...)
static OnInfoChangedListener mCallback;
public HoroscopeChoice() {}
/******************************
* Callback
********/
public static void OnInfoChangedListener(OnInfoChangedListener callback) {
mCallback = callback;
}
public interface OnInfoChangedListener {
public void onInfoChanged(String horosocopo);
}
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_horoscope_choice,
container, false);
Button aquarius;
aquarius = (Button) view.findViewById(R.id.aquarius1);
final int id = view.getId();
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
String horoscopo = onClick2(v.getId());
Log.d("HoroscopeChoice", "push button->"+horoscopo);
mCallback.onInfoChanged(horoscopo);
}
};
aquarius.setOnClickListener(onClickListener);
public String onClick2(int id)
{
String horoscopo="";
if (id == R.id.aquarius1) {
horoscopo = "Aquarius";
}
}
(...)
Code of the Activity:
(...)
public void onInfoChanged(String horoscopo) {
Log.d("SchedulerActivity","OnInfoChanged na Scheduler->"+horoscope);
mHoroscopeDisplay = (TextView) findViewById(R.id.dailyHoroscope4);
mHoroscopeDisplay.setText(horoscopo);
}
When I do Log.d in the Fragment I get a value, on the Activity I have no value. Does anyone knows what is wrong?
You can do it via interface callbacks, but there is an even easier way with a great third party library called EventBus that is perfect for this kind of thing. You can send any object from one place to the other.
All you need to do is post the Event and create a listener method wherever is needed. Follow their guide, it's very easy.
Don't use a static listener object, especially to store something like an Activity. You should instead make the listener an instance variable. The standard pattern for using interface communication between Fragments and Activities is by using onAttach().
private OnInfoChangedListener mCallback;
#Override
public void onAttach(Activity activity) {
if (!(activity instanceof OnInfoChangedListener)) {
throw new IllegalStateException("Activity must implement OnInfoChangedListener!");
}
mCallback = (OnInfoChangedListener) activity;
}
#Override
public void onDetach() {
mCallback = null;
}
Hi Iam using Event bus to pass data from one fragment to another Fragment
From fragment-1 I am doing as below
#Override
public void onPause() {
bsValues = new BoreShaftValues(strtext, strtextshaft);
bus.post(bsValues);
super.onPause();
}
In Fragment-2 I registered bus in OnActivitycreated
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
bus.register(this);
}
Then I placed OnEvent() method in fragment-2
public void onEvent(BoreShaftValues event){
boregradeselect.setText(event.getBoreData());
shaftgradeselect.setText(event.getShaftData());
}
Below is my BoreshaftVales class
public class BoreShaftValues {
private String boredata;
private String shaftdata;
public BoreShaftValues(String boredata, String shaftdata){
this.boredata = boredata;
this.shaftdata = shaftdata;
}
public String getBoreData(){
return boredata;
}
public String getShaftData(){
return shaftdata;
}
}
But this OnEvent() method is not getting called at all. Am i doing it the rightway?
I typically try to tie EventBus back to the Activity and yet enable it to be loosely coupled. So in the Fragment lifecycle I register EventBus in the onAttach and unregister it in the onDetach methods in the fragment.
So far, i was using Volley but after going through the Robospice library, and it's advantages over other network libraries, i started using it in my current project.
It working fine, but since it's lifecycle is tied to the activity not fragments, i implemented the same in fragment like this.
public class MainActivityFragment extends Fragment {
private SpiceManager spiceManager = new SpiceManager(JacksonSpringAndroidSpiceService.class);
private static final String KEY_LAST_REQUEST_CACHE_KEY = "lastRequestCacheKey";
private String lastRequestCacheKey;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
performRequest(mSort);
return rootView;
}
#Override
public void onSaveInstanceState(Bundle outState) {
if (!TextUtils.isEmpty(lastRequestCacheKey)) {
outState.putString(KEY_LAST_REQUEST_CACHE_KEY, lastRequestCacheKey);
}
super.onSaveInstanceState(outState);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
if (savedInstanceState != null && savedInstanceState.containsKey(KEY_LAST_REQUEST_CACHE_KEY)) {
lastRequestCacheKey = savedInstanceState.getString(KEY_LAST_REQUEST_CACHE_KEY);
spiceManager.addListenerIfPending(MovieDataResult.class, lastRequestCacheKey,
new ListMovieRequestDataListener(movieImageAdapter, getActivity(),progressDialog));
spiceManager.getFromCache(MovieDataResult.class, lastRequestCacheKey, DurationInMillis.ONE_MINUTE,
new ListMovieRequestDataListener(movieImageAdapter, getActivity(),progressDialog));
}
super.onActivityCreated(savedInstanceState);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
spiceManager.start(getActivity());
}
#Override
public void onStop() {
super.onStop();
if (spiceManager.isStarted()) {
spiceManager.shouldStop();
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
mSort = Utility.getPreferredSorting(getActivity());
setUpProgressDialog();
}
private void performRequest(String mSort) {
MovieDataRequest movieDataRequest = new MovieDataRequest(apiKey,mSort);
lastRequestCacheKey = movieDataRequest.createCacheKey();
spiceManager.execute(movieDataRequest, lastRequestCacheKey,
DurationInMillis.ONE_MINUTE, new ListMovieRequestDataListener(movieImageAdapter, getActivity(),progressDialog));
}
}
This works fine, i was wondering, if it follows the lifecycle. As, i am starting spicemanager onAttach() and stopping onStop() and onRestoreInstance() getting the cached data.
Basically, this is how it works here-->
spicemanager starts when fragment is attached
then .execute() is called for network request
spicemanager is destroyed onStop()
Also, is it a good approach to have a spicemanager for each activity?
I also pondered about this question recently as I was creating spiceManagers in both my activities and fragment classes.
This actually results in me having spiceManager objects in multiple places and for me, I do not think it was the most efficient way to do things.
Eventually, what I decided to do was to create a static instance of the spiceManager in my activity:
public static SpiceManager spiceManager = new SpiceManager(SpiceService.class);
Then use this static spiceManager within my fragments:
MainActivity.spiceManager.start(getActivity());
I also think that the most efficient way to do this is probably if you use interfaces to transfer data that you want handled by robospice back to the activity and just use the spiceManager inside your activity to do all the work. However, this can be a major piece of work.
I am using EventBus to post the result to a fragment when an http request is made successfully. This works nice when there's a one subscriber and one publisher relation.
However, in my application I have a screen that uses a ViewPager with tabs. And because the pages are very similar, I use the same fragment with a different parameter corresponding to each tab, to download data.
The Fragment looks something along these lines:
public class MyFragment extends Fragment{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EventBus.getDefault().register(this);
}
public void onEvent(ServerResponse response) {
updateUi(response);
}
#Override
public void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}
And you might guess already what happens when data is received.
Since the are many subscribers with the same signature, waiting a ServerResponse, the responses don't go to the corresponding tab, but the same response is received and displayed in every fragment, and the data gets mixed.
Do you have any idea how to solve this?
Hei! Same problem here, but I have a solution.
The problem is that you have a lot of Fragments (instances from same object) and all of them are listening the same event, so all of them are updated when you post an event.
When you post an event, try send a position and when you instantiate your Fragment you need to store the page adapter position. After just check if the event has the same position of your Fragment.
For example:
public static QuestionFragment newInstance(int position) {
QuestionFragment fragment = new QuestionFragment();
Bundle args = new Bundle();
args.putInt(ARG_POSITION, position);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
vMain = inflater.inflate(R.layout.fragment_question, container, false);
EventBus.getDefault().post(new GetQuestionEvent(mPosition));
return vMain;
}
public void onEvent(GetQuestionEvent e) {
if (e.getQuestion().getPosition() == mPosition) {
TextView tvPostion = (TextView) vMain.findViewById(R.id.tv_position);
tvPostion.setText("" + e.getQuestion().getPosition());
}
}