How to save loaded listView state in fragment? - android

I have one activity, fragment with listView and fragment with details for each listView item. I am getting fragments data from API. How should I save loaded date and listView position correctly to be able to restore it when I am returning back to the listView?
I tried to implement this solution Once for all, how to correctly save instance state of Fragments in back stack? but I cannot restore my listView correctly.
My MainActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Set the fragment initially
listFragment = new ListFragment();
fragmentTransaction =
getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, listFragment);
fragmentTransaction.commit();
if (savedInstanceState != null) {
//Restore the fragment's instance
listFragment = (ListFragment)getSupportFragmentManager().getFragment(savedInstanceState, "listContent");
}
...
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
//Save the fragment's instance
getSupportFragmentManager().putFragment(outState, "listContent", listFragment);
}
and ListFragment
public class ListFragment extends Fragment {
public static final String REQUEST_TAG = "ProjectListFragment";
private int page;
private View view;
private RelativeLayout loading ;
private PagingListView listView;
private PagingProjectListAdapter adapter;
private ArrayList<String> projects = new ArrayList<>();
private ArrayList<String> loadedProjects = new ArrayList<>();
public ListFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_list, container, false);
listView = (PagingListView) view.findViewById(R.id.projectsListView);
loading = (RelativeLayout) view.findViewById(R.id.loading);
//page = 1;
adapter = new PagingProjectListAdapter(getContext(), ListFragment.this);
listView.setAdapter(adapter);
listView.setHasMoreItems(true);
// Inflate the layout for this fragment
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (savedInstanceState != null) {
// FIXME not used
listView.onFinishLoading(true, projects);
//Restore the fragment's state here
} else {
projects.clear();
page = 1;
listView.setPagingableListener(new PagingListView.Pagingable() {
#Override
public void onLoadMoreItems() {
new CustomVolleyAsyncTask().execute();
}
});
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("currentPosition", 0);
//Save the fragment's state here
}
public void itemClickMethod(View detailsView) {
LinearLayout linearLayout = (LinearLayout) detailsView;
String bid = linearLayout.getContentDescription().toString();
Bundle bundle = new Bundle();
String k = "ProjectID";
bundle.putString(k, bid);
DetailsFragment detailsFragment = new DetailsFragment();
detailsFragment.setArguments(bundle);
final FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, detailsFragment, "DetailsFragmentTag");
ft.addToBackStack(null);
ft.commit();
}
private class CustomVolleyAsyncTask extends SafeAsyncTask<List<String>> implements Response.Listener,
Response.ErrorListener {
public List<String> status = null;
private RequestQueue mQueue;
#Override
public List<String> call() throws Exception {
mQueue = CustomVolleyRequestQueue.getInstance(view.getContext())
.getRequestQueue();
String url = "http://www.myapi.com/api/v1/data/" + Integer.toString(page);
final CustomJSONObjectRequest jsonRequest = new CustomJSONObjectRequest(Request.Method
.GET, url,
new JSONObject(), this, this);
jsonRequest.setTag(REQUEST_TAG);
mQueue.add(jsonRequest);
// TODO rm redundant result
return status;
}
#Override
public void onErrorResponse(VolleyError error) {
// FIXME check no response case crash
//mTextView.setText(error.getMessage());
}
#Override
public void onResponse(Object response) {
try {
JSONArray projectsJSON = new JSONArray(((JSONObject) response).getString("projects"));
loadedProjects.clear();
for (int i=0; i < projectsJSON.length(); i++) {
loadedProjects.add(projectsJSON.getJSONObject(i).toString());
}
page++;
listView.onFinishLoading(true, loadedProjects);
if (loading.getVisibility() == View.VISIBLE && !listView.isLoading()){
listView.setVisibility(View.VISIBLE);
loading.setVisibility(View.GONE);
}
} catch (JSONException e) {
e.printStackTrace();
}}}
}
currently, my savedInstanceState is always null, what am I missing?

I think, that your fragment created twice, when configuration changed. Here Staffan explain, why this happend. I resolve similar problem by this way (in activity onCreate):
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment fragment = fragmentManager.findFragmentByTag(TAG);
if(fragment==null)
fragmentManager.beginTransaction()
.add(R.id.container, NewsFragment.newInstance(),TAG)
.commit();

Related

Trying to Pass data from Activity to Fragment

I'm new in Android Development here i'm trying to pass data from Activity to Fragment
"gameid" <-- i want to pass this data from Activity to Fragment
im using this code which is not working anyone tell me whats wrong in this code !!!!
Activity Class
public CardView matchCard;
ImageView gamebanner;
TabLayout tabLayout;
ViewPager2 pager2;
bettingpage_tabviewer adapter;
private ArrayList<MatchModel> gList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_betting_page);
String gameid = getIntent().getStringExtra(GAME_ID);
String banner = getIntent().getStringExtra(BANNER);
Bundle bundle = new Bundle();
bundle.putString("gameId", gameid);
// set Fragmentclass Arguments
matchtab fragobj = new matchtab();
fragobj.setArguments(bundle);
gamebanner = findViewById(R.id.gamebanner);
tabLayout = findViewById(R.id.bettingtabs);
pager2 = findViewById(R.id.bettingpagetab);
Glide.with(this).load(banner).into(gamebanner);
FragmentManager fm = getSupportFragmentManager();
final FragmentTransaction fragmentTransaction = fm.beginTransaction();
final matchtab myFragment = new matchtab();
adapter = new bettingpage_tabviewer(fm, getLifecycle());
pager2.setAdapter(adapter);
tabLayout.addTab(tabLayout.newTab().setText("Match Tab"));
tabLayout.addTab(tabLayout.newTab().setText("Result Tab"));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
pager2.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
pager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageSelected(int position) {
tabLayout.selectTab(tabLayout.getTabAt(position));
}
});
}
}
Fragment Class
want to show "gameid" data in TextView named "demo"
public class matchtab extends Fragment {
private static final String ARG_PARAM1 = "gameId";
private String gameId;
RecyclerView matachrecyclerview;
private MyAdapter adapter;
private ArrayList<Model> gList;
public matchtab() {
// Required empty public constructor
}
public static matchtab newInstance(String gameId) {
matchtab fragment = new matchtab();
Bundle args = new Bundle();
args.putString("gameId", gameId);
fragment.setArguments(args);
return fragment;
}
//
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
gameId = this.getArguments().getString("gameId");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_matchtab, container, false);
TextView demo;
demo = v.findViewById(R.id.demotxt);
demo.setText(gameId);
// Recycler View
matachrecyclerview = v.findViewById(R.id.matchrecyclerview);
gList = new ArrayList<>();
FirebaseDatabase db = FirebaseDatabase.getInstance();
DatabaseReference root = db.getReference("Match").child("game1");
root.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()){
Model model = dataSnapshot.getValue(Model.class);
gList.add( new Model(model.title,model.amt));
Log.i("THE_CURRENT_USER:::", model.toString());
}
LinearLayoutManager im = new LinearLayoutManager((getContext()));
matachrecyclerview.setLayoutManager(im);
adapter = new MyAdapter(getContext(),gList);
matachrecyclerview.setAdapter(adapter);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
return v;}
}
This Code is not working please tell me what's wrong in this code
You shouldn't use constructor in fragment, remove it. You're directly passing the parameters to fragment with bundle.put in activity, no need for newinstance in fragment then. Try to remove default constructor and newinstance and try again.
dude you created two instances of fragment and set the arguments to 1 but use 2 without arguments
Use first capital letter in class name and some useful names)
try to do
in your fragment:
public static MyFragment newInstance(String gameId) {
MyFragment fragment = new MyFragment();
Bundle args = new Bundle();
args.putString("gameId", gameId);
fragment.setArguments(args);
return fragment;
}
in your activity:
MyFragment.newInstance(gameId)

Passing Search Result From fragment To Another fragment

I Have Fragment That Do the Search And Get The Result From The Server
and send the Result To another Fragment withe list view
To show it . the result it show empty list nothing show
Fragment Search
public class Search extends Fragment implements View.OnClickListener {
EditText Drugname;
Button SendDrug;
private ProgressDialog plog;
private List<SearchAvailDrug> drugreq= new ArrayList<SearchAvailDrug> () ;
private CustomListAdapter adapter;
public Search() {
// Required empty public constructor
}
OnHeadlineSelectedListener mCallback;
// Container Activity must implement this interface
public interface OnHeadlineSelectedListener {
public void onArticleSelected(int position);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mCallback = (OnHeadlineSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnHeadlineSelectedListener");
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_search, container, false);
Drugname=(EditText) view.findViewById(R.id.searchdrug);
SendDrug =(Button) view.findViewById(R.id.startdrug) ;
adapter = new CustomListAdapter(this, drugreq);
SendDrug.setOnClickListener(this);
return view;
}
#Override
public void onClick(View v) {
SendDataUp(Drugname.getText().toString());
}
#Override
public void onDetach() {
super.onDetach();
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
private void SendDataUp(final String Drugname){
Log.i("SendDataUp","Start");
String url = Urls.URL_AvailDrug;
//showing dialog box
plog = new ProgressDialog(getActivity());
plog.setIndeterminate(false);
plog.setMessage("Registration Please wait ...");
plog.show();
// Start Using Volley
// Request a string response
StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#RequiresApi(api = Build.VERSION_CODES.KITKAT)
#Override
public void onResponse(String response) {
hidePDialog();
String UserIdNum=null;
Log.v("Search",response);
try {
if (response.equalsIgnoreCase(String.valueOf(false)))
{
hidePDialog();
;
}
else
{
for (int i = 0; i < response.length(); i++) {
JSONArray RideJArray = new JSONArray(response);
SearchAvailDrug ride = new SearchAvailDrug(); ride.setDrugBrand(jpart.getString("BrandName")); ride.setPharmcyNameAr(jpart.getString("phname_ar")); ride.setPharmcyNameEn(jpart.getString("phname_ar"));
ride.setPhinfo(jpart.getString("info")); ;
ride.setLang(jpart.getDouble("lang"));
ride.setLat(jpart.getDouble("lat"));
drugreq.add(ride);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
adapter.notifyDataSetChanged();
Bundle args = new Bundle();
args.putParcelableArrayList("mylist", (ArrayList<? extends Parcelable>) drugreq);
Fragment fragment = new Listpage();
fragment.setArguments(args);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_nav_main, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
// shownextpage();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
hidePDialog();
// Error handling
System.out.println("Something went wrong!");
error.printStackTrace();
Toast.makeText(getActivity(), "FAILED TO CONNECT",Toast.LENGTH_LONG).show();
}
})
{
#Override
public String getBodyContentType() {
return "application/x-www-form-urlencoded; charset=UTF-8";
}
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String>();
params.put("BrandName",Drugname);
return params;
}
};
// Add the request to the queue
int socketTimeout = 30000;//30 seconds - change to what you want
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
stringRequest.setRetryPolicy(policy);
Volley.newRequestQueue(getActivity()).add(stringRequest);
}
private void shownextpage(){
Bundle args = new Bundle();
Fragment fragment = new Listpage();
fragment.setArguments(args);
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_nav_main, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
private void hidePDialog() {
if (plog != null) {
plog.dismiss();
plog = null;
}
}
}
and it show it in the another fragment List view
and here is the code
public class Listpage extends Fragment {
private ListView listView;
private CustomListAdapter adapter;
private List<SearchAvailDrug> drugreq= new ArrayList<SearchAvailDrug>() ;
public Listpage() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_Listpage_list, container, false);
Bundle args = getArguments();
ArrayList<SearchAvailDrug>arrayList;
// arrayList = (ArrayList<SearchAvailDrug>)args.getParcelableArrayList("mylist");
drugreq = args.getParcelableArrayList("mylist");
adapter = new CustomListAdapter(this, drugreq);
listView = (ListView) view.findViewById(R.id.listpharmcy);
listView.setAdapter(adapter);
return view;
}
}
the problem it show me empty list view
after i load the fragment
You should follow the "newInstance" recommendation when dealing with Fragments and arguments, otherwise, Android OS might recreate the instance with null arguments.
https://stackoverflow.com/a/9245510/6828464

all Fragment recreating when a switching through fragments using tablayout

I am creating an application which is based on Tabs using tablayout. I didn't use viewpager. My logic is that users can create fragments (Tabs) like adding tabs in chrome so that whenever user clicks add button a new tab is created with a fragment. Now i need to save unique time stamp of each fragment created time in shared preference so that whenever i move to one fragment i can use that shared reference timestamp value to do unique function intended for that particular fragment.
But i don't know where to save that timestamp. I tried to get the time in milliseconds in Oncreate function of Fragment but whenever I switch between tabs everytime the onCreate call so that each time i switch between tabs the shared preference value changes as i added it in onCreate in Fragments.
My Logic is that it should only create once a fragment is created when user clicks add and must be able to use that in fragments.
As every time i switch to other fragement it just reinitilize all view and onCreate in called. so i could not set timestamp in oncreate..
Please help me
my Activity code is:
public class TabActivity extends AppCompatActivity{
public static TabActivity instance;
private FragmentChild fragmentOne;
private TabLayout allTabs;
ImageView add;
ImageView imageButtonAdd2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_activity);
getAllWidgets();
bindWidgetsWithAnEvent();
setupTabLayout();
}
public static TabActivity getInstance() {
return instance;
}
private void getAllWidgets() {
allTabs = (TabLayout) findViewById(R.id.simpleTabLayout);
add = findViewById(R.id.addButton);
imageButtonAdd2 = findViewById(R.id.imageButtonAdd2);
}
private void setupTabLayout() {
allTabs.addTab(allTabs.newTab().setText("ONE"),true);
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
allTabs.addTab(allTabs.newTab().setText("NEW_TAB"),true);
bindWidgetsWithAnEvent();
}
});
imageButtonAdd2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*Bundle bundle = new Bundle();
bundle.putString("data", String.valueOf(0));
fragmentSecond = new SecondFragment();
fragmentSecond.setArguments(bundle);
replaceFragment(fragmentSecond,"SecondFragment");*/
}
});
}
private void bindWidgetsWithAnEvent()
{
allTabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
setCurrentTabFragment(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
private void setCurrentTabFragment(int tabPosition)
{
Bundle bundle = new Bundle();
bundle.putString("data", String.valueOf(tabPosition));
fragmentOne = new FragmentChild();
fragmentOne.setArguments(bundle);
replaceFragment(fragmentOne,"FirstFragment");
}
public void replaceFragment(Fragment fragment, String fragmentName) {
long time= System.currentTimeMillis();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.simpleFrameLayout, fragment,fragmentName);
//ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}
public void backStackFragment(Fragment fragment, String fragmentName) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.simpleFrameLayout, fragment,fragmentName);
ft.addToBackStack(null);
//ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
}
#Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
Log.i("MainActivity", "popping backstack");
fm.popBackStack();
} else {
Log.i("MainActivity", "nothing on backstack, calling super");
super.onBackPressed();
}
}
}
FragmentChild class:
public class FragmentChild extends Fragment {
String childname;
TextView textViewChildName;
EditText editText;
private GridView mGridView;
private ListItem mListItem;
private ListView mListview;
private ProgressBar mProgressBar;
private ProductViewAdapter mGridAdapter;
private ListViewAdapter mListAdapter = null;
private ArrayList<GridItem> mGridData;
private ArrayList<ListItem> mListData = null;
ListView listView;
CheckInterNetConnection check ;
Boolean isInternetPresent = false;
PreferenceHelper prefs;
private TabLayout tabLayout;
private ViewPagerAdapter adapter;
public static ViewPager viewPager;
String posid = "";
int page =0;
String title = "";
TabLayout allTabs;
int tab_position = 0;
long time=0;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//GlobalBus.getBus().register(this);
View view = inflater.inflate(R.layout.fragment_child, container, false);
Bundle bundle = getArguments();
childname = bundle.getString("data");
Log.e("onCreateView","onCreateView");
getIDs(view);
setEvents();
return view;
}
// Store instance variables based on arguments passed
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
time= System.currentTimeMillis();
page = getArguments().getInt("someInt", 0);
title = getArguments().getString("someTitle");
Log.e("onCreate","onCreate");
}
private void getIDs(View view) {
//textViewChildName = (TextView) view.findViewById(R.id.textViewChild);
//textViewChildName.setText(childname);
//editText = (EditText) view.findViewById(R.id.editText);
//editText.setText("");
}
private void setEvents() {
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.e("onViewCreated","onViewCreated");
}
#Override
public void onDestroyView() {
super.onDestroyView();
// Unregister the registered event.
EventBus.getDefault().unregister(this);
}
public static FragmentChild newInstance(int page, String title) {
FragmentChild fragmentFirst = new FragmentChild();
Bundle args = new Bundle();
args.putInt("someInt", page);
args.putString("someTitle", title);
fragmentFirst.setArguments(args);
return fragmentFirst;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.e("onActivityCreated","onActivityCreated");
allTabs = (TabLayout) getActivity().findViewById(R.id.simpleTabLayout);
mGridView = (GridView) getView().findViewById(R.id.gridView);
prefs = new PreferenceHelper(getActivity());
mGridData = new ArrayList<>();
mGridAdapter = new ProductViewAdapter(getActivity(), R.layout.grid_product_layout, mGridData);
mGridView.setAdapter(mGridAdapter);
mListview = (ListView) getView().findViewById(R.id.list);
mListData = new ArrayList<>();
mListAdapter = new ListViewAdapter(getActivity(), R.layout.list_row, mListData);
mListview.setAdapter(mListAdapter);
adapter = new ViewPagerAdapter(getFragmentManager(), getActivity(), viewPager, tabLayout);
}
#Override
public void onStart() {
super.onStart();
Log.e("onStart","onStart");
EventBus.getDefault().register(this);
tab_position=allTabs.getSelectedTabPosition();
//Log.e("TAB ID",String.valueOf(tab_position));
prefs.save(String.valueOf(tab_position),"tab-"+time);
check = new CheckInterNetConnection(getActivity());
isInternetPresent = check.isConnectingToInternet();
if (isInternetPresent) {
fetchProducts(tab_position);
}
}
#Override
public void onResume() {
super.onResume();
Log.e("onResume","onResume");
}
#Override
public void onPause() {
EventBus.getDefault().unregister(this);
Log.e("onPause","onPause");
super.onPause();
}
#Subscribe
public void onEvent(GlobalBus event){
posid = event.getMessage();
//Toast.makeText(getActivity(), event.getMessage(), Toast.LENGTH_SHORT).show();
}
public void fetchProducts(int tabPosition){
String tabid = prefs.getString(String.valueOf(tabPosition),"0");
Fragment fragment = getFragmentManager().findFragmentById(R.id.simpleFrameLayout);
String tag = (String) fragment.getTag();
//Log.e("URL","http://35.184.41.163/phpmyadmin/app/demo/products.php?tabid="+tabid+"&tab_position="+tabPosition);
RestClientHelper.getInstance().get("http://35.184.41.163/phpmyadmin/app/demo/products.php", new RestClientHelper.RestClientListener() {
#Override
public void onSuccess(String response) {
parseResult(response);
mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
try {
ListItem items;
GridItem item = (GridItem) parent.getItemAtPosition(position);
items = new ListItem();
items.setName(item.getTitle());
items.setType(item.getDescription());
mListData.add(items);
}
catch(Exception e){
}
finally {
mListAdapter.setGridData(mListData);
}
}
});
}
#Override
public void onError(String error) {
}
});
}
private void parseResult(String result) {
try {
JSONObject response = new JSONObject(result);
JSONArray posts = response.optJSONArray("products");
GridItem item;
if(posts.length() <= 0){
RelativeLayout ly = (RelativeLayout) getView().findViewById(R.id.noOps);
ly.setVisibility(View.VISIBLE);
}
else {
// RelativeLayout ly = (RelativeLayout) getView().findViewById(R.id.noOps);
//ly.setVisibility(View.INVISIBLE);
mGridData.clear();
mGridAdapter.setGridData(mGridData);
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
String id = post.optString("id");
String title = post.optString("name");
String description = post.optString("description");
String image = post.optString("image");
String qty = post.optString("qty");
String quantityin = post.optString("quantityin");
String price = post.optString("price");
item = new GridItem();
item.setId(id);
item.setTitle(title);
item.setDescription(description);
item.setImage(image);
item.setQuantity(qty);
item.setQuantityIn(quantityin);
item.setUnitprice(price);
mGridData.add(item);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
finally {
mGridAdapter.setGridData(mGridData);
}
}
}
UPDATE as suggested by #Larry Hsiao
public class TabActivity extends AppCompatActivity{
public static TabActivity instance;
private FragmentChild fragmentOne;
PreferenceHelper prefs;
private TabLayout allTabs;
ImageView add;
ImageView imageButtonAdd2;
private final List<Fragment> fragments = new ArrayList<>(); // maintain the instance for switching
private int currentIndex = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tab_activity);
prefs = new PreferenceHelper(TabActivity.this);
getAllWidgets();
//bindWidgetsWithAnEvent();
setupTabLayout();
bindWidgetsWithAnEvent();
}
public static TabActivity getInstance() {
return instance;
}
private void getAllWidgets() {
allTabs = (TabLayout) findViewById(R.id.simpleTabLayout);
add = findViewById(R.id.addButton);
add.performClick();
imageButtonAdd2 = findViewById(R.id.imageButtonAdd2);
}
private void setupTabLayout() {
int locfirst = allTabs.getSelectedTabPosition();
locfirst = locfirst+1;
allTabs.addTab(allTabs.newTab().setText("TAB"+locfirst),true);
/*long time= System.currentTimeMillis();
prefs.save("tab_"+locfirst,"tab_"+time);*/
fragments.add(newFragment(0));
addFragment(fragments.get(0));
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int loc = allTabs.getSelectedTabPosition();
loc = loc+1;
allTabs.addTab(allTabs.newTab().setText("TAB"+loc),true);
fragments.add(newFragment(loc));
addFragment(fragments.get(loc));
/*bindWidgetsWithAnEvent();
long time= System.currentTimeMillis();
prefs.save("tab_"+loc,"tab_"+time);*/
}
});
imageButtonAdd2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*Bundle bundle = new Bundle();
bundle.putString("data", String.valueOf(0));
fragmentSecond = new SecondFragment();
fragmentSecond.setArguments(bundle);
replaceFragment(fragmentSecond,"SecondFragment");*/
}
});
}
private Fragment newFragment(int position) {
Fragment fragment = new FragmentChild();
Bundle bundle = new Bundle();
bundle.putString("position", String.valueOf(position));
fragment.setArguments(bundle);
return fragment;
}
private void addFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.simpleFrameLayout, fragment);
transaction.commit();
}
private void changingTab(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.hide(fragments.get(currentIndex));
if (manager.getFragments().contains(fragment)) {
transaction.show(fragment);
}else {
transaction.add(R.id.simpleFrameLayout,fragment);
}
transaction.commit();
}
private void bindWidgetsWithAnEvent()
{
allTabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
int nextPageIndex = (currentIndex + 1) % 2; // only two fragment switching
changingTab(fragments.get(nextPageIndex));
currentIndex = nextPageIndex;
//setCurrentTabFragment(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
\
#Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
Log.i("MainActivity", "popping backstack");
fm.popBackStack();
} else {
Log.i("MainActivity", "nothing on backstack, calling super");
super.onBackPressed();
}
}
}
This force closes with this error:
FATAL EXCEPTION: main
Process: com.eazypos.app, PID: 13624
java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
at java.util.ArrayList.get(ArrayList.java:308)
at com.eazypos.app.TabActivity$3.onTabSelected(TabActivity.java:115)
at android.support.design.widget.TabLayout.dispatchTabSelected(TabLayout.java:1165)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1158)
at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1128)
at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1427)
at android.support.design.widget.TabLayout.addTab(TabLayout.java:483)
at android.support.design.widget.TabLayout.addTab(TabLayout.java:465)
at com.eazypos.app.TabActivity$1.onClick(TabActivity.java:62)
at android.view.View.performClick(View.java:4780)
at android.view.View$PerformClick.run(View.java:19866)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
REMOVE TAB FUNCTION
public void removeTab(int position) {
Toast.makeText(getActivity(), "REMOVING --> "+position, Toast.LENGTH_SHORT).show();
prefs.remove("tab_"+position);
if (allTabs.getChildCount() > 0) {
allTabs.removeTabAt(position);
}
}
To save the value only once.. in timeStamp in the shared prefs just use this in each fragment..
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getActivity() == null)
{
// generate time stamp in miliseconds as you are doing
// and save it in shared prefs
// this will be called only once..
}
}
OR YOU CAN TRY IN :-
UPDATE onCreate of fragmentChild
time= System.currentTimeMillis();
SharedPreferences sharedPreferences = getActivity().getSharedPreferences("My_prefs_name",Context.MODE_PRIVATE);
String timeStamp = sharedPreferences.getString("timeStamp","");
if ( timeStamp.isEmpty())
{
// SAVE TIME IN SHAREPREFS
sharedPreferences.edit().putString("timeStamp",time).apply();
}
You should maintain the Fragment instance which you already create. (With FragmentManager or just keep it with variable might do the job)
The method setCurrentTabFragment() in Activity which creating new Fragment is invoked every time user click tab. As the result, fragment always run through the onCreate()
// this method invoke every time user click the tab
private void setCurrentTabFragment(int tabPosition){
Bundle bundle = new Bundle();
bundle.putString("data", String.valueOf(tabPosition));
fragmentOne = new FragmentChild(); // creating new Fragment
fragmentOne.setArguments(bundle);
replaceFragment(fragmentOne,"FirstFragment");
}
Edited:
Use List to maintain the Fragment instance we already create.
Switch Fragment with hide()/show() provided by FragmentManager, using add() if the Fragment not added to FragmentManager before.
Sample Code:
public class MainActivity extends AppCompatActivity {
private final List<Fragment> fragments = new ArrayList<>();
private int currentIndex = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TabLayout tabLayout = findViewById(R.id.tabLayout);
// initial with one page
Fragment firstFragment = newFragment(0);
fragments.add(firstFragment);
addFragment(firstFragment);
tabLayout.addTab(tabLayout.newTab().setText("Initial tab"));
// user events
findViewById(R.id.main_createTab).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fragments.add(newFragment(tabLayout.getTabCount()));
tabLayout.addTab(tabLayout.newTab().setText("Pages " + tabLayout.getTabCount()));
}
});
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
int nextPageIndex = tab.getPosition();
if (currentIndex == nextPageIndex){
return;
}
changingTab(fragments.get(nextPageIndex));
currentIndex = nextPageIndex;
}
#Override public void onTabUnselected(TabLayout.Tab tab) {}
#Override public void onTabReselected(TabLayout.Tab tab) {}
});
}
private Fragment newFragment(int position) {
Fragment fragment = new FragmentWithLog();
Bundle bundle = new Bundle();
bundle.putString("position", String.valueOf(position));
fragment.setArguments(bundle);
return fragment;
}
private void addFragment(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.main_fragmentFrame, fragment);
transaction.commit();
}
private void changingTab(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.hide(fragments.get(currentIndex));
if (manager.getFragments().contains(fragment)) {
transaction.show(fragment);
} else {
transaction.add(R.id.main_fragmentFrame, fragment);
}
transaction.commit();
}
}

ListViewFragment (Fragment that contains ListView) only created once, at the first time

I'm trying to update ListView's data after downloaded JSON data, but it didn't work because onCreate and onCreateView methods are only working at first time.
I noticed it when I put debugging point to that two methods but the debugging line never entered there. The response json is correct, but the UI couldn't be updated by parsing ListViewFragment.init(myNewDataList).
Here is my ListViewFragment,
public class ListViewFragment extends Fragment{
ListView listView;
ArrayList<Incident> incidentLists;
public static ListViewFragment init(ArrayList<Incident> incidentLists) {
ListViewFragment listViewFragment = new ListViewFragment();
listViewFragment.setIncientLists(incidentLists);
return listViewFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_listview, container,
false);
initUI(view);
adapter = new ListViewAdapter(getActivity(), incidentLists);
adapter.notifyDataSetChanged();
listView.setAdapter(adapter);
return view;
}
public ArrayList<Incident> getIncientLists() {
return incidentLists;
}
public void setIncientLists(ArrayList<Incident> incientLists) {
this.incidentLists = incientLists;
}
}
And I parse the data to fragment after the JSON downloaded like following snippet, this is AsyncHttpClient's onSuccess method.
#Override
public void onSuccess(int statusCode, Header[] headers,
String content) {
try {
ArrayList<Incident> incidentList = new ArrayList<Incident>();
JSONObject content_ = new JSONObject(content);
JSONArray response = content_.getJSONArray("nodes");
for (int i = 0; i < response.length(); i++) {
JSONObject nodeObj = response.getJSONObject(i)
.getJSONObject("node");
Incident incident = Utils.parseNodeObjectToIncident(nodeObj);
incidentList.add(incident);
}
Fragment fragment = ListViewFragment.init(incidentList);
Utils.replaceFragment(fragment, MainActivity.this);
} catch (JSONException e) {
Toast.makeText(getApplicationContext(),"JSON Exception", Toast.LENGTH_LONG).show();
}
}
I doubt that my ListViewFragment only happen once at the first time because it is confusing with BackStack and transaction stuffs at Utils.replaceFragment().
public static void replaceFragment(Fragment fragment,
AppCompatActivity activity) {
String backStateName = fragment.getClass().getName();
String fragmentTag = backStateName;
FragmentManager fragmentManager = activity.getSupportFragmentManager();
boolean fragmentPopped = fragmentManager.popBackStackImmediate(
backStateName, 0);
if (!fragmentPopped
&& fragmentManager.findFragmentByTag(fragmentTag) == null) {
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
fragmentTransaction.replace(R.id.frame_container, fragment,
fragmentTag);
// fragmentTransaction.add(R.id.frame_container, fragment);
fragmentTransaction
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragmentTransaction.addToBackStack(backStateName);
// fragmentTransaction.commitAllowingStateLoss();
fragmentTransaction.commitAllowingStateLoss();
}
}
Any Help?
Basically your problem is that you are not able to update list when you have got latest set of information from server.
I would have solved this problem with the below code:
In list view adapter keep a method as written below:
public class ListFragmentAdapter extends <your adapter extension>{
private Context context;
private List<Incident> incidents;
//constructor
public ListFragmentAdapter (Context context,List<Incident> initialIncidentList){
this.context = context;
this.incidents = initialIncidentList;
}
public void updateListFragment(List<Incident> latestIncidents){
incidents.addAll(latestIncidents);
this.notifyDataSetChanged();
}
}
Comment below if you have any doubts

Fragment with ViewPager issue

I want to create soemthing like this:
The ViewPager is attached to an adapter which has 2 fragments. One to list the upcoming orders and the other to list the past orders.
So the image shown above has a main fragment which hosts the ViewPager, and the adapter creates 2 fragments as children of the main fragment.
For sake of simplicity I'll call the main fragment as "Parent fragment" and the two fragments supplied by the adapter as "children fragments".
Once the parent fragment is created or resumed it has to fetch a list of data from the server and pass it to the two children fragment(The children fragments will process the list of data and display the necessary data). Both the children fragments have a listView, and each listView row item is clickable.
Now, the data fetched by the parent fragment has to be passed to the children fragments before the ViewPager is attached to the adapter. So I do not attach the adapter to the ViewPager in the onCreate method of the parent fragment, but rather once the list of data is fetched, I attach the adapter to the ViewPager in the onPostExecute method of the async task after the data is fetched.
This works fine the first time, but once I click on a listView row item of the child fragment and then press the back button, the getItem() method of the adapter is not called, but the onResume methods of the children fragments are called even before the data is fetched from the server.
So I guess the android framework remembers that the children fragment have already been created, and does not recreate them again.
How do I ensure that the children fragments are created/called only after the data is fetched from the server in the parent fragment?
I am adding some code for clarity.
BookingHistory.java(Parent Fragment)
public class BookingHistory extends android.support.v4.app.Fragment {
ViewPager mPager;
SlidingTabLayout mTabs;
Toolbar toolBar;
View view;
private ProgressDialog progress;
private OrderTask mOrderTask = null;
UserFunctions userFunctions = null;
OrderFunctions orderFunctions = null;
private BookingHistoryListener mListener;
private List<Order> mOrderList;
PlacedOrders upcomingOrders;
PlacedOrders pastOrders;
public BookingHistory() {
// Required empty public constructor
}
#Override
public void onResume() {
super.onResume();
mOrderList = null;
mPager = null;
mTabs = null;
upcomingOrders = null;
pastOrders = null;
progress = new ProgressDialog(getActivity());
fetchOrders();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_booking_history, container, false);
toolBar = (Toolbar) view.findViewById(R.id.toolbar_s);
if (toolBar != null) {
TextView tv = (TextView) view.findViewById(R.id.toolbar_title);
toolBar.setTitle("");
tv.setText("History");
}
return view;
}
class MyPagerAdapter extends FragmentPagerAdapter {
String tabs[] = {"Upcoming", "Past"};
public MyPagerAdapter(android.support.v4.app.FragmentManager fm) {
super(fm);
}
#Override
public android.support.v4.app.Fragment getItem(int position) {
if (position == 0) {
upcomingOrders = PlacedOrders.newInstance(Constants.DATE_TODAY_FUTURE);
upcomingOrders.getOrderList(mOrderList);
return upcomingOrders;
} else {
pastOrders = PlacedOrders.newInstance(Constants.DATE_PAST);
pastOrders.getOrderList(mOrderList);
return pastOrders;
}
}
#Override
public CharSequence getPageTitle(int position) {
return tabs[position];
}
#Override
public int getCount() {
return 2;
}
}
public void fetchOrders() {
if (mOrderTask != null) {
return;
}
progress.show();
mOrderTask = new OrderTask(getActivity());
mOrderTask.execute((Void) null);
}
public class OrderTask extends AsyncTask<Void, Void, Boolean> {
private final Activity mActivity;
OrderTask(Activity activity) {
mActivity = activity;
}
#Override
protected Boolean doInBackground(Void... params) {
userFunctions = new UserFunctions();
orderFunctions = new OrderFunctions();
return orderFunctions.getList(userFunctions.getToken(mActivity));
}
#Override
protected void onPostExecute(final Boolean success) {
mOrderTask = null;
progress.dismiss();
if (success) {
mOrderList = UserProfile.getOrders();
//attaching the view pager to adapter here!
mPager = (ViewPager) view.findViewById(R.id.pager);
mTabs = (SlidingTabLayout) view.findViewById(R.id.sliding_tabs);
mTabs.setDistributeEvenly(true);
mTabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.white);
}
});
mPager.setAdapter(new MyPagerAdapter(getChildFragmentManager()));
mTabs.setViewPager(mPager);
} else {
//Error handling stuff
}
}
}
}
PlacedOrders.java(Children Fragments)
public class PlacedOrders extends android.support.v4.app.Fragment {
private static String flag;
private int dateFlag;
private PlacedOrdersListener mListener;
UserFunctions userFunctions = null;
OrderFunctions orderFunctions = null;
private PlacedOrdersAdapter ordersAdapter;
private ProgressDialog progress;
private List<Order> mOrderList;
private List<Order> mPendingOrderList;
private List<Order> mCompletedOrderList;
public static PlacedOrders newInstance(int date) {
PlacedOrders fragment = new PlacedOrders();
Bundle args = new Bundle();
args.putInt(flag, date);
fragment.setArguments(args);
return fragment;
}
public void getOrderList(List<Order> orderList) {
this.mOrderList = orderList;
}
public PlacedOrders() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
dateFlag = getArguments().getInt(flag);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mPendingOrderList = new ArrayList<Order>();
mCompletedOrderList = new ArrayList<Order>();
return inflater.inflate(R.layout.fragment_placed_orders, container, false);
}
#Override
public void onResume() {
super.onResume();
displayOrders();
}
private void displayOrders() {
if (isVisible() && (mOrderList != null)) {
mPendingOrderList.clear();
mCompletedOrderList.clear();
ListView listViewOrder = (ListView) getView().findViewById(R.id.orderList);
if(dateFlag == Constants.DATE_TODAY_FUTURE) {
for(int i = 0; i < mOrderList.size(); i++) {
String status = mOrderList.get(i).status;
if(status.equals("PENDING") || status.equals("PROCESSING")) {
mPendingOrderList.add(mOrderList.get(i));
ordersAdapter = new PlacedOrdersAdapter(mPendingOrderList, getActivity().getLayoutInflater());
listViewOrder.setAdapter(ordersAdapter);
}
}
}
else if(dateFlag == Constants.DATE_PAST) {
for(int i = 0; i < mOrderList.size(); i++) {
String status = mOrderList.get(i).status;
if(status.equals("COMPLETE")) {
mCompletedOrderList.add(mOrderList.get(i));
ordersAdapter = new PlacedOrdersAdapter(mCompletedOrderList, getActivity().getLayoutInflater());
listViewOrder.setAdapter(ordersAdapter);
}
}
}
listViewOrder.setOnItemClickListener(new AdapterView.OnItemClickListener() {
//Display a new fragment on clicking
});
}
}
}
I had same issue and this was my solution :
In container fragment (fragment that contains tabs) in onViewCreated() method I created startFetch() method:
#Override
public void onViewCreated(View v, Bundle savedInstanceState) {
super.onViewCreated(v, savedInstanceState);
mViewPager = (ViewPager) v.findViewById(R.id.home_tab_pager);
mTabsHost= (TabLayout) getActivity().findViewById(R.id.appTabs);
startFetch();
}
Then in startFetch method i use Volley request and in onResponse method i update data and then add tabs :
public void startFetch(){
//Create volley request
String url = BuildConfig.API_GET_CATEGORIES;
final RequestQueue queue = VolleyService.getInstance(this.getContext()).getRequestQueue();
StringRequest request = new StringRequest(url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// we got the response, now our job is to handle it
try {
updateCategoryData(response);
} catch (RemoteException | OperationApplicationException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//something happened, treat the error.
Log.e("ErrorFETCH", error.networkResponse.toString());
}
});
queue.add(request);
}
My udpateCategory() method :
public void updateCategoryData(final String stream) throws RemoteException, OperationApplicationException {
//Update the data to SQLITE
setupTabs();
}
My setupTabs() method :
public void setUpTabs(){
ArrayList<Category> categories = new ArrayList<>();
Cursor data = getActivity().getContentResolver().query(
Category.Entry.CONTENT_URI, // URI
Category.PROJECTION, // Projection
Category.Entry.COLUMN_NAME_PARENT_ID + " = ?", // Selection
new String[]{"0"}, // Selection args
null);
if (data != null) {
while(data.moveToNext()){
categories.add(new Category(data));
}
}
TabsPagerAdapter mAdapter = new TabsPagerAdapter(getActivity().getSupportFragmentManager(), this.getActivity(), categories);
mViewPager.setAdapter(mAdapter);
mTabsHost.setupWithViewPager(mViewPager);
}

Categories

Resources