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
Related
Scene
I want to update the content of several fragments once I get the response from some HTTP requests.
My Idea
My implementation is something like this:
onCreate of activity, Bind ViewPagerAdapter to it. Then trigger the HTTP request to get data.
Once the request succeeds, update the content in Fragment.
Code
sendRequest. --> adapter.updateFragment(bundle) --> fragment.updateData(bundle);
Activity
protected void onCreate(Bundle savedInstanceState) {
Log.d("DetailedProduct-LifeCycle", "------------onCreate------------");
...
// Set ViewPager
viewPager = findViewById(R.id.view_pager);
adapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapter);
// Send Request
sendRequest();
...
}
public void sendRequest(){
Log.d("DetailedProduct", requestUrl);
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,
requestUrl,
null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
LinearLayout progressView = findViewById(R.id.progressView);
progressView.setVisibility(View.GONE);
bundle.putString("detail", response.toString());
Log.d("DetailedProduct", "get data:"+response.toString());
Log.d("DetailedProduct", "final Data:" + bundle.toString());
adapter.updateFragment(bundle);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("DetailedProduct", "Cannot get detailed data");
}
});
queue.add(jsonObjectRequest);
}
Adapter
public class ViewPagerAdapter extends FragmentPagerAdapter {
private SellerFragment sellerFragment;
private ShippingFragment shippingFragment;
private ProductSummaryFragment productSummaryFragment;
private FragmentManager fragManager;
public ViewPagerAdapter(FragmentManager fragmentManager){
super(fragmentManager);
sellerFragment = new SellerFragment();
shippingFragment = new ShippingFragment();
productSummaryFragment = new ProductSummaryFragment();
}
#NonNull
#Override
public Fragment getItem(int position) {
// ToDo:
Log.d("ViewPager", position+": ------------getItem----------");
switch (position){
case 0:
if(productSummaryFragment==null){
productSummaryFragment = new ProductSummaryFragment();
}
return productSummaryFragment;
case 1:
if(sellerFragment==null){
sellerFragment = new SellerFragment();
}
return sellerFragment;
case 2:
if(shippingFragment==null){
shippingFragment = new ShippingFragment();
}
return shippingFragment;
default:
return null;
}
}
#Override
public int getCount() {
return 3;
}
public void updateFragment(Bundle bundle){
Log.d("ViewPager", "------------updateData----------");
productSummaryFragment.updateData(bundle);
sellerFragment.updateData(bundle);
shippingFragment.updateData(bundle);
}
}
Fragment Sample
public class ShippingFragment extends Fragment {
private TextView shippingSection;
protected JSONObject data;
private AppCompatActivity mActivity;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.shipping_fragment_layout, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
shippingSection = view.findViewById(R.id.shipping_info_section_content);
setData();
}
#Override
public void onAttach(#NonNull Context context) {
Log.d("ShippingFragment", "-----------onAttach----------");
super.onAttach(context);
if(context instanceof AppCompatActivity){
Log.d("ShippingFragment", "---------bind mActivity Success-------");
mActivity = (AppCompatActivity)context;
}
}
#Override
public void onDetach() {
Log.d("ShippingFragment", "-----------onDetach----------");
super.onDetach();
}
// Same for all fragments
public void updateData(Bundle bundle){
Log.d("ShippingFragment", "--------------updateData------------");
setArguments(bundle);
if(mActivity==null){
Log.e("ShippingFragment", "------------activity disappears----------");
}
FragmentManager fragmentManager = mActivity.getSupportFragmentManager();
fragmentManager.beginTransaction().detach(this).attach(this).commit();
}
}
Problem
The log shows that updateData for fragments at position 0,1 works well. but it incurs error for the fragment at position 2.
The difference I found is that the adaptor didn't call getItem for position 2, which means onAttach of shippingFragment doesn't been called. So mActivity does not exist.
Without mActivity, using getFragmentManager in shippingFragment, get this error:
My intuition tells me that the problem must from the work flow of adapter or the fragmentManager transaction. But as a beginner of Android, I have spent all day on them, no clue.
How to fix it? By the way, is there better way to implement my scene?
Try to call viewPager.setOffscreenPageLimit(3) to make sure all 3 fragments are attached to the activity once the activity open.
I have a fragment in which I'm asking the user to select his team. It opens another fragment and user can select his team. But I'm stuck because unable to send the team details to the previous fragment.
User clicks the button to set home team, select the team from team_select_fragment, but I'm unable to send team details to the first fragment.
Below is the code for mathc_fragment where the user fills match data:
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_create_match, container, false);
Toolbar toolbar = rootView.findViewById(R.id.nav_toolbar);
((PlayerProfileActivity) getActivity()).getSupportActionBar().setTitle("Create Match");
city_name = rootView.findViewById(R.id.cityNameEditText);
ground_name = rootView.findViewById(R.id.groundNameEditText);
setupImageButton(rootView);
setupNumberOfPlayersButton(rootView);
setupHalfTimeButton(rootView);
preferenceConfig = new SharedPreferenceConfig(this.getContext());
requestQueue = Volley.newRequestQueue(getActivity());
Button startMatch = rootView.findViewById(R.id.start_match_bn);
return rootView;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
rootActivity = (PlayerProfileActivity) context;
} catch (Exception exception) {
rootActivity = null;
}
}
private void setupImageButton(final View rootView) {
//Select Home team
ImageButton homeTeamImageButton = rootView.findViewById(R.id.homeTeamImageButton);
homeTeamImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getChildFragmentManager().beginTransaction().add(R.id.create_match_container,new TeamSelect()).commit();
}
});
//select away team
ImageButton awayTeamImageButton = rootView.findViewById(R.id.awayTeamImageButton);
awayTeamImageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getChildFragmentManager().beginTransaction().add(R.id.create_match_container,new TeamSelect()).commit();
}
});
}
This is the code for team_select_fragment:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_team_select, container, false);
editText = rootView.findViewById(R.id.team_select_search);
recyclerView = rootView.findViewById(R.id.team_select_recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this.getContext()));
list_items = new ArrayList<>();
teamSelectAdapter = new TeamSelectAdapter(list_items, getContext());
recyclerView.setAdapter(teamSelectAdapter);
teamSelectAdapter.setOnItemClickListener(this);
loadRecyclerViewData();
return rootView;
}
private void loadRecyclerViewData() {
stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response);
int success = jsonObject.getInt("success");
if(success==1){
JSONArray jsonArray = jsonObject.getJSONArray("Teams");
for (int i=0; i < jsonArray.length(); i++){
JSONObject jsonObject_current = jsonArray.getJSONObject(i);
TeamSelectModelClass teamSelectModelClass = new TeamSelectModelClass(
jsonObject_current.getString("team_id"),
jsonObject_current.getString("team_name"),
jsonObject_current.getString("team_logo_url")
);
list_items.add(teamSelectModelClass);
}
teamSelectAdapter.notifyDataSetChanged();
}else if(success==0){
String message = jsonObject.getString("Message");
Toast.makeText(getContext(),message,Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getContext(), error.getMessage(), Toast.LENGTH_LONG).show();
}
})
};
requestQueue = Volley.newRequestQueue(getContext());
requestQueue.add(stringRequest);
}
#Override
public void onItemClick(int position) {
TeamSelectModelClass clickedItem = list_items.get(position);
String team_id = clickedItem.getTeam_id();
String team_name = clickedItem.getTeam_name();
String team_logo = clickedItem.getTeam_logo_url();
}
2 solution :
-If you back to the fragment (by create new fragment),create a call back like
A extends Fragment(){
public A setMethod(X a){
this.a = a;
return this;
}
}
and in fragment B call
new A().setData(yourdata)
Second solution is you just add your data to SharePreference and get it when you return from the other fragment
use following method in your parent Activity(Activity where you are loading your fragments)
public void changeFragment(Fragment nextFragment, boolean addToBackstack) {
int containerId = R.id.content_frame;
FragmentManager fragmentManager = getSupportFragmentManager();
final FragmentTransaction transaction = fragmentManager
.beginTransaction();
if (fragmentManager.findFragmentById(containerId) != null) {
fragmentName = fragmentManager.findFragmentById(containerId);
}
transaction.replace(containerId, nextFragment);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if (addToBackstack == true) {
transaction.addToBackStack(fragmentName.getClass().getName());
}
currentFragment = nextFragment.getClass().toString();
transaction.commit();
}
and call this method in your fragments wherever you want as follows
YourFragment yourFragment = new YourFragment ();
final MainActivity mainActivity = (MainActivity) activity;
mainActivity.changeFragment(yourFragment, true);
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();
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);
}
I am running into an issue where I have a fragment, which contains a tab layout/view pager which handles 3 sub fragments, and when I open the main fragment the first time all the data in the sub fragments shows up properly, but when I re-open the main fragment again (clicking on a seperate listview item), the data does not get populated properly (even though it exists).
I also noticed that the only time the sub-fragment gets its data is when view paging over to the last tab, or when rotating the screen. Also, when I try to move the screen to the right using the view pager the tab indicator will get stuck mid way between the first and second tab.
What can I do to fix this issue?
Fragment Adapter
public class DetailFragmentPagerAdapter extends FragmentPagerAdapter {
Context context;
final int PAGE_COUNT = 3;
private String tabTitles[] = new String[] { "Plot", "Trailers", "Reviews" };
private Movie movie;
public DetailFragmentPagerAdapter(FragmentManager fm, Context context, Movie movie) {
super(fm);
this.context = context;
this.movie = movie;
}
#Override
public Fragment getItem(int position) {
if(position == 0){
return PlotFragment.newInstance(movie);
} else if (position == 1){
return TrailerFragment.newInstance();
} else if (position == 2){
return ReviewFragment.newInstance();
} else {
Log.e("RETURNING NULL", "RETURNING NULL");
return null;
}
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public CharSequence getPageTitle(int position) {
return tabTitles[position];
}
}
Main Fragment
public class MovieItemDetailFragment extends Fragment implements View.OnClickListener {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
public String TAG = MovieItemDetailFragment.class.getCanonicalName();
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
private View view;
private TextView tvTitle, tvReleaseDate, tvRating;
private ImageView ivMoviePoster;
private Movie movie;
private Handler handler;
private Button btnFavorite;
private boolean isFavorited = false;
private View.OnClickListener mOnClickListener;
private ViewPager viewpager;
private TabLayout tablayout;
private DetailFragmentPagerAdapter adapter;
// TODO: Rename and change types and number of parameters
public static MovieItemDetailFragment newInstance(String param1, String param2) {
MovieItemDetailFragment fragment = new MovieItemDetailFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public MovieItemDetailFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_movie_item_detail, container, false);
init();
return view;
}
private void init() {
handler = new Handler();
this.movie = (Movie) getArguments().getSerializable("MOVIE");
tvTitle = (TextView) view.findViewById(R.id.tvTitle);
tvReleaseDate = (TextView) view.findViewById(R.id.tvReleaseDate);
tvRating = (TextView) view.findViewById(R.id.tvAvgRating);
ivMoviePoster = (ImageView) view.findViewById(R.id.ivMoviePoster);
btnFavorite = (Button) view.findViewById(R.id.btnFavorite);
btnFavorite.setOnClickListener(this);
viewpager = (ViewPager) view.findViewById(R.id.pager);
tablayout = (TabLayout) view.findViewById(R.id.sliding_tabs);
adapter = new DetailFragmentPagerAdapter(getActivity().getSupportFragmentManager(),
getActivity(), getMovie());
viewpager.setAdapter(adapter);
adapter.notifyDataSetChanged();
tablayout.post(new Runnable() {
#Override
public void run() {
tablayout.setupWithViewPager(viewpager);
}
});
mOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
isFavorited = true;
btnFavorite.setBackground(getActivity().getResources().getDrawable(R.drawable.favorite_content_selector));
}
};
setElementValues();
}
private void setElementValues() {
handler.post(new Runnable() {
#Override
public void run() {
tvTitle.setText(getMovie().getTitle());
tvReleaseDate.setText(getMovie().getRelease_date());
tvRating.setText(String.valueOf(getMovie().getVote_average()));
Picasso.with(getActivity()).load(getMovie().getFull_poster_path()).into(ivMoviePoster);
if (isFavorited) {
btnFavorite.setBackground(getActivity().getResources().getDrawable(R.drawable.favorite_content_selector));
} else {
btnFavorite.setBackground(getActivity().getResources().getDrawable(R.drawable.favorite_blank_content_selector));
}
}
});
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnFavorite:
if (isFavorited) {
isFavorited = false;
btnFavorite.setBackground(getActivity().getResources().getDrawable(R.drawable.favorite_blank_content_selector));
showSnackbar("I thought that was one of your favorites.");
} else {
isFavorited = true;
btnFavorite.setBackground(getActivity().getResources().getDrawable(R.drawable.favorite_content_selector));
}
break;
}
}
private void showSnackbar(String msg) {
Snackbar
.make(view, msg, Snackbar.LENGTH_LONG)
.setAction(R.string.snackbar_action, mOnClickListener)
.setActionTextColor(getActivity().getResources().getColor(R.color.material_yellow_400))
.show();
}
/**
* 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
public void onFragmentInteraction(Uri uri);
}
public Movie getMovie() {
return movie;
}
}
Instead of calling
adapter = new DetailFragmentPagerAdapter(getActivity().getSupportFragmentManager(), getActivity(), getMovie());
try:
adapter = new DetailFragmentPagerAdapter(getChildFragmentManager(), getActivity(), getMovie());
This is also working for me.
Basically, the difference is that Fragment's now have their own internal FragmentManager that can handle Fragments. The child FragmentManager is the one that handles Fragments contained within only the Fragment that it was added to. The other FragmentManager is contained within the entire Activity.
for further detail about getChildFragmentManager()
visit this question
[What is difference between getSupportFragmentManager() and getChildFragmentManager()?