I have 3 tabs in my main activity. In the 2nd tab I have a fragment that has a list and I am using Retrofit to get data from my server and display it in the list.
In my 2nd fragment I have:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment_recents, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
getBooks();
}
private void getBooks(){
final ProgressDialog loading = ProgressDialog.show(getContext(), "Fetching Data", "Please wait...", false, false);
/* Retrofit code: */
//Creating a rest adapter
RestAdapter adapter = new RestAdapter.Builder()
.setEndpoint(ROOT_URL)
.build();
//Creating an object of our api interface
MyAPI api = adapter.create(MyAPI.class);
//Defining the method
api.getBooks(new Callback<List<MyPojo>>() {
#Override
public void success(List<MyPojo> list, Response response) {
//Dismissing the loading progressbar
loading.dismiss();
//Storing the data in our list
pojos = list;
mAdapter = new MyAdapter(getContext(), pojos);
mRecyclerView.setAdapter(mAdapter);
}
#Override
public void failure(RetrofitError error) {
//you can handle the errors here
loading.dismiss();
Log.v("Error: ", "" + error);
}
});
}
my problem is that the progress dialog is shown as soon as the app is launched in the 1st tab..I want it to fetch the data only when the 2nd tab is opened.
According to the developer guide for fragments, a fragment's lifecycle (see Figure 2 in the link) is only active (i.e. displayed and the user can interact with it) between the onResume() and onPause() android callbacks.
If you want something to only occur when the fragment is displayed, place the code for showing it in the onResume() callback. You can pre-fetch or do other setup in other callbacks if you like.
Put the network code in your second Fragment's onResume()
#Override
public void onResume() {
super.onResume();
final ProgressDialog loading = ProgressDialog.show(getContext(), "Fetching Data", "Please wait...", false, false);
(and the rest is the Retrofit code)
}
Related
RecyclerView position not saved after screen rotation and moves to the beginning of the list.
RecyclerView находиться в Fragment, added the following code to my project, after which, in theory, the position should be saved, but this does not happen
#Override
public void onPause() {
super.onPause();
state = RLM_tasks.onSaveInstanceState();
}
Help to figure out why the list does not save position and solve this problem
Fragment completely
public class FragmentList extends Fragment {
CardView cv_list;
private FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
private CollectionReference collectionReference = firebaseFirestore.collection("Tasks");
private AdapterTasksList adapterTasksList;
private RecyclerView rv_tasks;
private RecyclerView.LayoutManager RLM_tasks;
Parcelable state;
public static FragmentList newInstance() {
return new FragmentList();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_list, container, false);
}
#Override
public void onViewCreated(#NonNull final View view, #Nullable Bundle savedInstanceState)
{
cv_list = requireView().findViewById(R.id.cv_list);
cv_list.setOnClickListener(v -> requireActivity().onBackPressed());
Query query = collectionReference.orderBy("TurnTasks", Query.Direction.DESCENDING);
FirestoreRecyclerOptions<ItemTasks> firestoreRecyclerOptions = new FirestoreRecyclerOptions.Builder<ItemTasks>()
.setQuery(query, ItemTasks.class)
.build();
adapterTasksList = new AdapterTasksList((ClickTasksBlanc) getContext(), firestoreRecyclerOptions);
adapterTasksList.startListening();
rv_tasks = requireView().findViewById(R.id.rv_list);
RLM_tasks = new LinearLayoutManager(getActivity());
RLM_tasks.onRestoreInstanceState(state);
rv_tasks.setHasFixedSize(false);
rv_tasks.setLayoutManager(RLM_tasks);
rv_tasks.setNestedScrollingEnabled(true);
rv_tasks.setAdapter(adapterTasksList);
}
#Override
public void onPause() {
super.onPause();
state = RLM_tasks.onSaveInstanceState();
}
}
I have suspicions that the whole problem is that the list is re-created when the screen is rotated, and therefore it cannot re-revert to the previous position.
For these kind of situation you have to use model view- view model called mvvm you can get more detail & tutorial from official website and also see the some example of tutorial
You can save layoutManager state in ViewModel then get the state value when the fragment re-created
You can check the sample code here https://code.luasoftware.com/tutorials/android/android-jetpack-navigation-lost-state-after-navigation/#maintain-state-via-viewmodel
I have two activities. When an item in a RecyclerView is selected, it takes the user to the second activity and fills in the details with the related RecyclerView item.
In the second RecyclerView activity, there is a Spinner. Depending on the item selected in the spinner, different RecyclerViews become visible/invisible to the user on the second activity.
How do I make it work so that the information is sent from the first activity to command the spinner on what to do?This is how Second Activity looks
SecondActivity.java
public class SecondActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
private TextView tv_title, tv_description;
private ImageView PartiesThumbnailImg,PartiesCoverImg;
private RecyclerView RvPartyMembers;
private PartyMembersAdapter partyMembersAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_parties_detail);
Spinner spinner = findViewById(R.id.spnConstituencies);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.constituencies, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(this);
//ini views
iniViews();
//Setting up members list
setupRvPartyMembers();
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String text = parent.getItemAtPosition(position).toString();
Toast.makeText(parent.getContext(), text, Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
void iniViews() {
RvPartyMembers = findViewById(R.id.rv_party_members);
String partiesTitle = getIntent().getExtras().getString("title");
String partiesDescription = getIntent().getExtras().getString("description");
int imageResourceId = getIntent().getExtras().getInt("imgURL");
int imagecover = getIntent().getExtras().getInt("imgCover");
PartiesThumbnailImg = findViewById(R.id.detail_members_img);
Glide.with(this).load(imageResourceId).into(PartiesThumbnailImg);
PartiesThumbnailImg.setImageResource(imageResourceId);
PartiesCoverImg = findViewById(R.id.detail_members_cover);
Glide.with(this).load(imagecover).into(PartiesCoverImg);
tv_title = findViewById(R.id.tvPartyTitle);
tv_title.setText(partiesTitle);
tv_description = findViewById(R.id.tvPartyDesc);
tv_description.setText(partiesDescription);
}
void setupRvPartyMembers(){
List<PartyMembers> mdata = new ArrayList<>();
mdata.add(new PartyMembers("name",R.drawable.members_brendangriffin_fg));
mdata.add(new PartyMembers("name",R.drawable.members_brendangriffin_fg));
mdata.add(new PartyMembers("name",R.drawable.members_brendangriffin_fg));
partyMembersAdapter = new PartyMembersAdapter(this,mdata);
RvPartyMembers.setAdapter(partyMembersAdapter);
RvPartyMembers.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.HORIZONTAL,false));
}
These are the important pieces of code of the FirstActivity.java
#Override
public void onPartiesItemClick(PartiesOireachtas partiesOireachtas, ImageView partiesImageView) {
Intent intent = new Intent(getContext(),PartiesDetailActivity.class);
intent.putExtra("title", partiesOireachtas.getTitle());
intent.putExtra("description",partiesOireachtas.getDescription());
intent.putExtra("imgURL", partiesOireachtas.getThumbnail());
intent.putExtra("imgCover",partiesOireachtas.getCoverPhoto());
and
Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//RecyclerView Setup
//int data
lstPartiesOireachtas = new ArrayList<>();
lstPartiesOireachtas.add(new PartiesOireachtas("Fianna Fáil", "example1", R.drawable.fianna_fail_logo,R.drawable.fianna_fail_cover));
lstPartiesOireachtas.add(new PartiesOireachtas("Sinn Féin", "example2", R.drawable.sinn_fein_logo,R.drawable.sinn_fein_cover));
lstPartiesOireachtas.add(new PartiesOireachtas("Fine Gael", "example4", R.drawable.fine_gael_logo,R.drawable.fine_gael_cover));
lstPartiesOireachtas.add(new PartiesOireachtas("Green Party", "example9", R.drawable.green_party_logo,R.drawable.green_party_cover));
lstPartiesOireachtas.add(new PartiesOireachtas("Social Democrats", "example3", R.drawable.soc_dems_logo,R.drawable.soc_dems_cover));
lstPartiesOireachtas.add(new PartiesOireachtas("Independent", "example2", R.drawable.independent_party_logo,R.drawable.independent_party_cover));
As you probably noticed an activity doesn't have a default constructor, but uses an onCreate(Bundle savedInstanceState) method. This means you should pass your information using this Bundles, or use something like SharedPreferences / SQLite. Since SharedPreferences / SQLite is a bit overkill for this in my opinion, you can add the object upon creating an intent.
Intent intent = new Intent();
intent.putExtra("name", parcelableObject);
If you want to pass a custom object you have to implement the Parcelable interface, this is pretty straightforward since you can basically auto generate all code for this in Android studio (just hit alt-enter a few times). For more information you can check out the following link.
https://developer.android.com/reference/android/os/Parcelable
In the receiving activity you can do the following:
Bundle bundle = getIntent().getExtras();
Object object = bundle.getObject("name"); //Don't forget to cast!
I have a fragment which doesn't contain anything at the application start, but after the data is loaded it should show the loaded data. I do all my data loading in MainActivity in function onDataLoaded which implements DataLoadedListener. After the data is loaded the function sends the data (ArrayList) as a parameter through the function call (initializeAdapter()). Then, the function initializeAdapter() gets it and initialize custom made adapter (adapter is a global object, initialized in initializeAdapter() and used in onCreateView()).
I guess that I should refresh fragment view after the data is loaded and the adapter is initialized, but I don't know how to do it. I tried in a lot of ways but didn't make it.
onDataLoaded function in MainActivity which calls initializeAdapter()
#Override
public void onDataLoaded(List<Grad> gradovi, List<Ponuda> ponude) {
Spinner spinnerGradovi = (Spinner) findViewById(R.id.gradovi_spinner);
ArrayAdapter<String> adapterGradovi;
List<String> listaGradova = new ArrayList<>();
ArrayList<Ponuda> ponudaArrayList = new ArrayList<Ponuda>();
ponudaLista = ponude;
gradLista = gradovi;
for(Grad grad : gradovi ){
listaGradova.add(grad.getNaziv());
}
for(Ponuda ponuda : ponude){
ponudaArrayList.add(ponuda);
}
adapterGradovi = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, listaGradova);
spinnerGradovi.setAdapter(adapterGradovi);
Fragment fragmentGet = svePonudeFragment;
((SvePonudeFragment)fragmentGet).initializeAdapter(ponudaArrayList);
}
and this is a Fragment
public class SvePonudeFragment extends Fragment {
private RecyclerView rv;
RVAdapter adapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.sve_ponude_fragment, container, false);
rv = (RecyclerView) rootView.findViewById(R.id.rv);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
rv.setLayoutManager(llm);
rv.setAdapter(adapter);
return rootView;
}
public void initializeAdapter(List<Ponuda> preuzetePonude){
adapter = new RVAdapter(preuzetePonude);
//this isn't working
/*FragmentManager manager = getActivity().getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft = manager.beginTransaction();
ft.detach(this).attach(this).commit();*/
//this is not working, neither
Fragment frg = getFragmentManager().findFragmentByTag("sve_ponude_fragment_tag");
final android.support.v4.app.FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();
}
}
I am also interested in how to make an empty adapter which loads if data is not loaded yet? And when the data is loaded to fill out another adapter and use it.
Initialize adapter before you set. If you interested to change you approach I can give suggestions: Create a constructor for you fragment which you can pass the ArrayList. OnCreate or OnCreateView you can initialize the adapter and pass the list into. After setting adapter notifyDataChanges and to check if there is data please use some Logs when you pass the data and before you pass the data. Do not directly blame the adapter or fragment control your data. Besides I suggest you to study more using fragments + RecyclerView. I am posting one example that you can look at but the data load in the fragment.
public class CategoryFragment extends Fragment {
//Class Tag
private static final String TAG = CategoryFragment.class.getSimpleName();
//Fragments base context
private Context mContext;
//RecyclerView widget
private RecyclerView mRecyclerView;
//RecyclerView's Layout Manager
private RecyclerView.LayoutManager mLayourManager;
//RecyclerView's Adapter
private CategoryFragmentAdapter mCategoryFragmentAdapter;
//Category Data List
private ArrayList<Category> mCategoryList;
//Interface object
onCategoryItemClick mCallBackCategory;
#Override
public void onAttach(Context context) {
super.onAttach(context);
//Instantiate base context
mContext = context;
//Instantiate interface
mCallBackCategory = (onCategoryItemClick)getActivity();
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Instantiate Category List
mCategoryList = new ArrayList<Category>();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
//Custom fragment view instantiating
View view_fragment_category = inflater.inflate(R.layout.fragment_items, container, false);
//Instantiating Fragment's recycler view
mRecyclerView = (RecyclerView) view_fragment_category.findViewById(R.id.recycle_categories);
//Instantiate RecycleView's Layout Manager: LinearLayoutManager is one of the default
mLayourManager = new LinearLayoutManager(mContext);
//Setting layout manager for recycler view
mRecyclerView.setLayoutManager(mLayourManager);
//Retrieve data from server, populate the category data list and set the RecyclerView's adapter
getCategories();
//Instantiate the adapter and push the data
mCategoryFragmentAdapter = new CategoryFragmentAdapter(mContext, mCategoryList);
//RecyclerView item click listener
mCategoryFragmentAdapter.SetOnItemClickListener(new CategoryFragmentAdapter.OnItemClickListener() {
#Override
public void onItemClick(View v , int position) {
//Test display
//Toast.makeText(mContext, mCategoryList.get(position).getId(),Toast.LENGTH_LONG).show();
//Push to Activity method with clicked item ID
mCallBackCategory.proceedToProducts(mCategoryList.get(position).getId());
}
});
return view_fragment_category;
}
I have a main Activity in which I created a ViewPager that instantiate 3 other Fragments. One of these is a GridView which makes a popup appear when the user click on one item. Then, in this popup, I have a simple button.
What I want to do is: when the user click on this button, I would like to access a method in my main Activity (that should change the current item of my ViewPager) and then dismiss the popup.
I tried everything I could, but I cannot achieve this... I can set up the click event on my popup and dismiss it easily, but I didn't find out how I can access a method (or even a variable) from my popup to my main Activity.
I will put my most relevant code in here so you can understand the structure of my classes (hopefully...).
My main Activity:
public class MainActivity extends FirstActivity{
private ViewPager mViewPager;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
// Set an Adapter on the ViewPager
mViewPager.setAdapter(new MainActivity_Adapter(getSupportFragmentManager()));
public void onSaveInstanceState(Bundle savedInstanceState)
{
menuBar.onSaveInstanceState(savedInstanceState);
}}
My ViewPager activity:
public class MainActivity_Adapter extends FragmentPagerAdapter{
public MainActivity_Adapter(FragmentManager fm)
{
super(fm);
}
#Override
public Fragment getItem(int position)
{
// Set the color background for each page
switch (position)
{
case 0:
return MainActivity_Inventory.newInstance();
case 1:
return MainActivity_Map.newInstance();
default:
return MainActivity_AR.newInstance();
}
}
// The number of Splash Screens to display
#Override
public int getCount()
{
return 3;
}}
My "Inventory" Fragment
public class MainActivity_Inventory extends Fragment implements View.OnClickListener{
public static MainActivity_Inventory newInstance()
{
MainActivity_Inventory frag = new MainActivity_Inventory();
Bundle b = new Bundle();
frag.setArguments(b);
return frag;
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Select the layout
int layout;
layout = R.layout.activity_inventory_01;
// Inflate the layout resource file
View view = getActivity().getLayoutInflater().inflate(layout, container, false);
// Set the grid view
GridView gridview = (GridView) view.findViewById(R.id.inventory_gridView);
gridview.setAdapter(new InventoryImageAdapter(super.getActivity()));
gridview.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView parent, View v, int position, long id)
{
// Create a popup to show item details
createPopup();
}
});
return view;
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
}
public void createPopup()
{
DialogFragment newFragment = new PopupActivity_Inventory();
newFragment.show(getFragmentManager(), "itemDetails");
}
#Override
public void onClick(View v)
{
}}
And my popup dialog fragment:
public class PopupActivity_Inventory extends DialogFragment{
#Override
public Dialog onCreateDialog(final Bundle savedInstanceState)
{
// Build the alert dialog
final Dialog dialog = new Dialog(this.getActivity());
// Get the layout inflater
final LayoutInflater inflater = getActivity().getLayoutInflater();
// Set up the dialog box
dialog.setContentView(inflater.inflate(R.layout.activity_inventory_popup_01, null));
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
dialog.getWindow().setGravity(Gravity.TOP);
//dialog.getWindow().getAttributes().y = 100;
(dialog.findViewById(R.id.brick_button_01)).setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
// When button is clicked, ACCESS MAIN ACTIVITY!
dialog.dismiss();
}
});
return dialog;
}}
I really hope you can help me with this... I really need to get it working. Thank you very much!
If you need further details or explanation, please just tell me.
The best thing to do is use EventBus library. I have a demo app in which you can add items to RecyclerView from anywhere within the app using EventBus. You can use it as a reference to simply do something else instead of current task. Here is the link to the repo:
https://github.com/code-crusher/android-demos/tree/master/EventBusDemo
And if you want to understand how it works you can refer to my article, it explains how to make communications like this easy:
https://medium.com/#code_crusher/eventbus-for-android
Hope it helps. Happy coding :)
Read this https://developer.android.com/training/basics/fragments/communicating.html
Look for "To allow a Fragment to communicate up to its Activity, you can define an interface in the Fragment class and implement it within the Activity...."
Another way to achieve it is using an EventBus and post events by Fragments to be caught by Activities.
I have an Activity A with a fragment frag2. Inside the fragment I have a RecyclerView and Adapter to show a list of custom class objects. Adding objects to the adapter is handled programmatically. I have a button inside TwoFragment that opens a FragmentDialog. I'd like to add an object to my Adapter by confirming this dialog, but it seems that the adapter is null when called from the FragmentDialog.
The same adapter is not null, and works if I call it from the fragment OnClick.
Moreover the adapter is null only after screen rotation, it works fine before rotating.
To communicate between the two Fragments I implement a communicator class in activity A.
Activity A
public void respond(String type) {
frag2.addSupport(type);
}
frag2
public RecyclerView rv;
public ArrayList<support> supports;
public myAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supports = new ArrayList<>();
adapter = new myAdapter(supports);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View layout = inflater.inflate( R.layout.fragment_two, container, false);
layout.setId(R.id.frag2);
if (savedInstanceState!=null)
{
supports = savedInstanceState.getParcelableArrayList("supports");
}
rv = (RecyclerView) layout.findViewById(R.id.rv);
adapter = new myAdapter(supports);
rv.setAdapter(myAdapter);
rv.setLayoutManager(new LinearLayoutManager(getActivity()));
rv.setItemAnimator(new DefaultItemAnimator());
#Override
public void onClick(View v) {
int id = v.getId();
switch (id){
case R.id.button1:
addSupport(type); // THIS WORKS ALWAYS, even after screen rotate
break;
case R.id.button2:
showDialog();
break;
}
}
public void showDialog(){
FragmentManager manager = getFragmentManager();
myDialog dialog = new myDialog();
dialog.show(manager, "dialog");
}
public void addSupport(String type){
adapter.addItem(new support(type)); // this line gives null pointer on adapter, but only if called after screen rotate and only if called from the dialog
}
dialog
communicator comm;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog, null);
comm = (myCommunicator) getActivity();
create = (Button) view.findViewById(R.id.button_ok);
create.setOnClickListener(this);
return view;
}
#Override
public void onClick(View v) {
if(v.getId()==R.id.button_ok)
{
// some controls to set type
comm.respond(type)
dismiss();
}
else {
dismiss();
}
myAdapter
public class myAdapter extends RecyclerView.Adapter<myAdapter.VH> {
private LayoutInflater inflater;
private ArrayList<support> data = new ArrayList<>();
// settings for viewholder
public myAdapter (ArrayList<support> data)
{
this.data=data;
}
public void addItem(support dataObj) {
data.add(dataObj);
notifyItemInserted(data.size());
}
}
logcat
FATAL EXCEPTION: main
java.lang.NullPointerException: Attempt to invoke virtual method 'myAdapter.addItem(myObject)' on a null object reference
I hope there are no mistakes, I shortened the code for better understanding. Keep in mind that everything works if I never rotate the screen.
I'm a beginner with android and I'm stuck with this for several days now. Please, help.
To understand the problem, it's as you say:
.. everything works if I never rotate the screen
So firstly to understand what happens on rotation, this is a quote from the Android Developer website:
Caution: Your activity will be destroyed and recreated each time the user rotates the screen. When the screen changes orientation, the system destroys and recreates the foreground activity because the screen configuration has changed and your activity might need to load alternative resources (such as the layout).
Ok, now to understand the error:
FATAL EXCEPTION: main
java.lang.NullPointerException: Attempt to invoke virtual method 'myAdapter.addItem(myObject)' on a null object reference
Essentially, in your dialog class, you have created a strong dependency by declaring :
comm = (myCommunicator) getActivity();
because comm references objects which would have been destroyed on rotation, hence the NullPointerException.
To further understand runtime changes, such as orientation changes, I'd recommend going through Handling Runtime Changes.
Update
Thank you for your answer, what would you recommend instead of comm = (myCommunicator) getActivity(); ?
The solution comes in 3 parts:
Make sure the onCreate of Activity A has the following:
#Override
public void onCreate(Bundle savedInstanceState) {
......
// find the retained fragment on activity restarts
FragmentManager fm = getFragmentManager();
frag2 = (Frag2) fm.findFragmentByTag(“frag2”);
// create frag2 only for the first time
if (frag2 == null) {
// add the fragment
frag2 = new Frag2();
fm.beginTransaction().add(frag2 , “frag2”).commit();
}
......
}
Add setRetainInstance(true) to the onCreate of frag2.
Remove the implicit referencing i.e. comm = (myCommunicator) getActivity();, and implement something more loosely coupled for dialog.
dialog
public interface Communicator {
void respond(String type);
}
Communicator comm;
....
public void addCommunicator(Communicator communicator) {
comm = communicator;
}
public void removeCommunicator() {
comm = null;
}
#Override
public void onClick(View v) {
if((v.getId()==R.id.button_ok) && (comm!=null))
{
// some controls to set type
comm.respond(type);
}
// Regardless of what button is pressed, the dialog will dismiss
dismiss();
}
This allows you do the following in frag2 (or any other class for that matter):
frag2
<pre><code>
public class Frag2 extends Fragment implements dialog.Communicator {
........
public void showDialog() {
FragmentManager manager = getFragmentManager();
myDialog dialog = new myDialog();
dialog.addCommunicator(this);
dialog.show(manager, "dialog");
}
#Override
public void respond(String type){
adapter.addItem(new support(type));
}
}