I have a TabLayout with 4 tabs in my Activity and I have made a Fragment per each Tab.
Below is my Activity code:
public class MyActivity extends AppCompatActivity {
private static final String TAG = "RecyclerView";
private Toolbar toolbar;
private static ViewPager viewPager;
private static TabLayout tabLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* Allow activity to show indeterminate progressbar */
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.student_regulations_list);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewPager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(onTabSelectedListener(viewPager));
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment1(), getString(R.string.titleA));
adapter.addFragment(new Fragment2(), getString(R.string.titleB));
adapter.addFragment(new Fragment3(), getString(R.string.titleC));
adapter.addFragment(new Fragment4(), getString(R.string.titleD));
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(3);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
}
private TabLayout.OnTabSelectedListener onTabSelectedListener(final ViewPager viewPager) {
return new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());//setting current selected item over viewpager
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
};
}
//View Pager fragments setting adapter class
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();//fragment arraylist
private final List<String> mFragmentTitleList = new ArrayList<>();//title arraylist
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
//adding fragments and title method
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
I have a RecyclerView in each fragment, and I fetch data from a Web Service using AsyncTask to show in the RecyclerView. Each item in RecyclerView has an ID and I want to When I switch between tabs and click on an item in RecyclerView, a Toast shows it's ID.
Below is a Fragment code:
public class Fragment1 extends Fragment implements ClickListener {
private static final String TAG = "RecyclerView";
private List<FeedItem> feedItemList;
private RecyclerView mRecyclerView;
private FeedsRecyclerAdapter mAdapter;
final String url = "a valid url";
private View rootView;
private ProgressBar progressBar;
public StuRegGeneralListFragment() {
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_student_regulations_list, container, false);
return rootView;
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
progressBar = (ProgressBar) rootView.findViewById(R.id.progress_bar);
/* Initialize recyclerview */
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
/*Downloading data from below url*/
new AsyncHttpTask().execute(url);
}
#Override
public void itemClicked(View view, int position) {
FeedItem item = feedItemList.get(position);
Intent intent = new Intent(getActivity(), JsonRequestFeedActivity.class);
intent.putExtra("url", Const.URL_JSON_OBJECT_REGS + item.getID());
intent.putExtra("pid", item.getID());
//startActivity(intent);
Toast.makeText(getActivity(), "Item ID: " + item.getID(), Toast.LENGTH_SHORT).show();
}
public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {
#Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
feedItemList = new ArrayList<FeedItem>();
}
#Override
protected Integer doInBackground(String... params) {
InputStream inputStream = null;
Integer result = 0;
HttpURLConnection urlConnection = null;
try {
/* forming th java.net.URL object */
URL url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
/* for Get request */
urlConnection.setRequestMethod("GET");
int statusCode = urlConnection.getResponseCode();
/* 200 represents HTTP OK */
if (statusCode == 200) {
BufferedReader r = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
response.append(line);
}
parseResult(response.toString());
result = 1; // Successful
} else {
result = 0; //"Failed to fetch data!";
}
} catch (Exception e) {
Log.d(TAG, e.getLocalizedMessage());
}
return result; //"Failed to fetch data!";
}
#Override
protected void onPostExecute(Integer result) {
progressBar.setVisibility(View.GONE);
/* Download complete. Lets update UI */
if (result == 1) {
updateRecyclerView();
} else {
Log.e(TAG, "Failed to fetch data!");
}
}
}
private void parseResult(String result) {
try {
JSONObject response = new JSONObject(result);
JSONArray posts = response.optJSONArray("posts");
/*Initialize array if null*/
if (null == feedItemList) {
feedItemList = new ArrayList<FeedItem>();
}
for (int i = 0; i < posts.length(); i++) {
JSONObject post = posts.optJSONObject(i);
FeedItem item = new FeedItem();
item.setID(post.optString("id"));
item.setDate(post.optString("date"));
item.setTitle(post.optString("title"));
item.setThumbnail(post.optString("thumbnail"));
feedItemList.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
public void updateRecyclerView() {
mAdapter = new FeedsRecyclerAdapter(getActivity(), feedItemList);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setClickListener(this);
}
}
Assuming each fragment has 5 items in RecyclerView (from ID 1 to 5 in fragment1, from ID 6 to 10 in fragment2, ...) I expect when I enter to my Activity and click on an item in fragment1 (for example first item), ID=1 be shown in Toast, but ID=16 is shown!
In fact because of viewPager.setOffscreenPageLimit(3); in my Activity, fragment1 and fagment2 and fragment3 and fragment4 are created and at the end, mAdapter contains item IDs 16-20, although I am in fragment1.
I expect after creating specified fragments by viewPager.setOffscreenPageLimit(int); each fragment has it's own adapter, but it's not happened.
Any help is appreciated.
I found out my mistake!
My Activity and Fragments code are correct, my mistake was in ClickListener of RecyclerView. It's implementation was not suitable in my case.
I had used a static clickListener in it, that was the point!
Related
There is a question similar to me, but that solution didn't work for my case.
The question I have referred is
this
I have a fragment named "HomeFragment" which consists of a VieWPager and TabLayout. I am adding tabs dynamically from the backend. So I am using another Fragment named "SecondFragment" for all tabs since all tabs contain a RecyclerView only. I am populating the RecyclerView onCreate() of the SecondFragment. My issue comes here that when I swipe or change the tab, the RecyclerView not updating correctly. On continuing swiping, the data changes but it does not correspond to the selected tab. I have logged the flow and I am getting correct data from backend on swiping, but it does not updating the RrecyclerView.
My HomeFragment class is
public class HomeFragment extends Fragment implements HTTPCallback {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private OnFragmentInteractionListener mListener;
private RecyclerView recyclerView;
private CardView cardview;
private boolean isShow;
View rootview;
private Toolbar toolbar;
private ImageView imageView, tabBg;
private CollapsingToolbarLayout collapsingToolbar;
private TabLayout mTabLayout;
Context context;
private ViewPager mViewPager, mViewPager1;
AppBarLayout appBarLayout;
Integer url_size;
int i;
boolean stopSliding = false;
String url, url2;
String message, version;
private ArrayList<HomeModel> planList;
JSONObject jsonObject, jsonObject2;
JSONArray jsonArray, jsonArray2;
ViewPagerAdapter adapter;
List<Product> products;
int numTab = 0;
private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;
public HomeFragment() {
}
public static HomeFragment newInstance(String param1, String param2) {
HomeFragment fragment = new HomeFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootview = inflater.inflate(R.layout.fragment_home, container, false);
appBarLayout = (AppBarLayout) rootview.findViewById(R.id.appbar);
mViewPager1 = (ViewPager) rootview.findViewById(R.id.view_pager);
collapsingToolbar = (CollapsingToolbarLayout) rootview.findViewById(R.id.collapsing_toolbar);
sharedPreferences = getContext().getSharedPreferences("spade", Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
mViewPager = (ViewPager) rootview.findViewById(R.id.viewpager);
mTabLayout = (TabLayout) rootview.findViewById(R.id.tabs);
mTabLayout.setSelectedTabIndicatorColor(Color.parseColor("#FF0000"));
mTabLayout.setSelectedTabIndicatorHeight((int) (5 * getResources().getDisplayMetrics().density));
mTabLayout.setTabTextColors(Color.parseColor("#727272"), Color.parseColor("#FF0000"));
new HTTPRequest(getContext(), null, null, HTTPRequest.METHOD.GET, this).execute(url2);
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if (position == 0) {
appBarLayout.setExpanded(true);
} else {
appBarLayout.setExpanded(false);
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
try {
} catch (Exception e) {
e.printStackTrace();
}
mTabLayout.setOnTabSelectedListener(
new TabLayout.ViewPagerOnTabSelectedListener(mViewPager) {
#Override
public void onTabSelected(TabLayout.Tab tab) {
super.onTabSelected(tab);
mViewPager.setCurrentItem(tab.getPosition());
numTab = tab.getPosition();
HomeModel browsePlan = planList.get(numTab);
editor.putString("tab", browsePlan.getName()).commit();
}
});
return rootview;
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onConnectionStarted() {
}
#Override
public void onConnectionFailed() {
}
#Override
public void onCompleted(JSONObject resultData) {
HomeModel model;
planList = new ArrayList<>();
adapter = new ViewPagerAdapter(getChildFragmentManager());
try {
jsonArray = resultData.getJSONArray("details");
editor.putString("tab", jsonArray.getJSONObject(0).getString("name"));
editor.commit();
for (int i = 0; i < jsonArray.length(); i++) {
jsonObject2 = jsonArray.getJSONObject(i);
model = new HomeModel();
model.setCatid(jsonObject2.getString("id"));
model.setImage(jsonObject2.getString("image"));
model.setName(jsonObject2.getString("name"));
planList.add(model);
setupViewPager(mViewPager, jsonObject2.getString("name"));
}
setAdapter();
} catch (JSONException e) {
e.printStackTrace();
}
}
private void setAdapter() {
appBarLayout.setExpanded(false);
mViewPager.setAdapter(adapter);
mTabLayout.setupWithViewPager(mViewPager);
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
private void setupViewPager(ViewPager mViewPager, String name) {
adapter.addFragment(new SecondFragment(), name);
mViewPager.setOffscreenPageLimit(1);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
SecondFragment class is
public class SecondFragment extends Fragment implements HTTPCallback {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
String mParam1;
String mParam2;
Button solo, grp;
View rootview;
Fragment fragment;
String url;
JSONObject jsonObject, jsonObject2;
JSONArray jsonArray, jsonArray2;
private ArrayList<Spaceship> planList;
RecyclerView rv;
private RecyclerHomeAdapter adapter = new RecyclerHomeAdapter(getContext(), planList);
;
private SharedPreferences sharedPreferences;
String tab_name;
private OnFragmentInteractionListener mListener;
public SecondFragment() {
}
public static SecondFragment newInstance(String s, String s1) {
SecondFragment fragment = new SecondFragment();
Bundle args = new Bundle();
return fragment;
}
#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) {
rootview = inflater.inflate(R.layout.fragment_second, container, false);
sharedPreferences = getContext().getSharedPreferences("spade", Context.MODE_PRIVATE);
tab_name = sharedPreferences.getString("tab", "onnumilla");
rv = (RecyclerView) rootview.findViewById(R.id.rv);
rv.setLayoutManager(new LinearLayoutManager(getContext()));
url = "My_url_here";
HashMap<String, String> data = new HashMap<String, String>();
data.put("name", tab_name);
new HTTPRequest2(getContext(), data, null, HTTPRequest2.METHOD.POST, this).execute(url);
return rootview;
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
adapter.notifyDataSetChanged();
// getFragmentManager().beginTransaction().detach(this).attach(this).commit();
}
}
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onConnectionStarted() {
}
#Override
public void onConnectionFailed() {
}
#Override
public void onCompleted(JSONObject resultData) {
Spaceship model;
planList = new ArrayList<>();
planList.clear();
try {
jsonArray = resultData.getJSONArray("products");
for (int i = 0; i < jsonArray.length(); i++) {
jsonObject2 = jsonArray.getJSONObject(i);
model = new Spaceship();
model.setName(jsonObject2.getString("package_name"));
model.setImage(jsonObject2.getString("images"));
planList.add(model);
}
setAdapter();
} catch (JSONException e) {
e.printStackTrace();
}
}
private void setAdapter() {
adapter = new RecyclerHomeAdapter(getContext(), planList);
adapter.notifyDataSetChanged();
rv.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
This doesn't work for me. But in the setUserVisibleHint(boolean isVisibleToUser) method when i add getFragmentManager().beginTransaction().detach(this).attach(this).commit();
instead of adapter.notifyDataSetChanged(); it works but it takes some time to hide previous data on swiping tab.
Anyone, please suggest me a solution. I have referred many questions but nothing works for me. All your response is appreciated.
This seems to be ViewPager page cashing issue. pls call below code from onCreateView()
of HomeFragment.
mViewPager.setOffscreenPageLimit(1);
I'm having MainActivity and three fragment activity. in MainActivity it gets data from REST service call. I want to pass REST data to all three fragments. how to achieve it?
here my code
MainActivty
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
private CustomListAdapter adapter;
private static final String TAG = MainActivity.class.getSimpleName();
public List<MenuItem> mainList = new ArrayList<MenuItem>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
JsonArrayRequest itemReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
try {
JSONArray jsonArray = response.getJSONArray(0);
// Parsing json
for (int i = 0; i < jsonArray.length(); i++) {
try {
JSONObject obj = jsonArray.getJSONObject(i);
MenuItem menuItem = new MenuItem();
menuItem.setName(obj.getString("name"));
menuItem.setImage(obj.getString("image"));
menuItem.setPrice(obj.getString("price"));
menuItem.setDesc(obj.getString("desc"));
mainList.add(menuItem);
} catch (JSONException e) {
e.printStackTrace();
}
}
}catch (JSONException e){
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new First(), "FIRST");
adapter.addFragment(new Second(), "SECOND");
adapter.addFragment(new Third(), "THIRD");
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
Fragment Activity
public class First extends Fragment{
private ProgressDialog pDialog;
private GridView gridView;
private CustomListAdapter adapter;
public First() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_one, container, false);
gridView = (GridView) view.findViewById(R.id.list);
adapter = new CustomListAdapter(getActivity(), startersList);
gridView.setAdapter(adapter);
return view;
}
}
In this line adapter = new CustomListAdapter(getActivity(), startersList);
I want to get list data from MainActivity
If you can make your menu item class implement Parcelable
How can I make my custom objects Parcelable?
Then it's simply a matter of passing arguments to the Fragment
Bundle args = new Bundle();
args.putParcelableArrayList("list", mainList) ;
Fragment first = new First();
first.setArguments(first);
adapter.addFragment(first, "FIRST");
Within the Fragment, you would use
getArguments().getParcelableArrayList("list")
Alternatively, you could also pass the JSON string into the arguments and parse it within the Fragment.
Note: however, that this only works if you move the viewpager setup method within onResponse. Otherwise, your Fragments are already created with empty lists.
Or you could implement that above logic here in the adapter
#Override
public Fragment getItem(int position) {
Fragment f = mFragmentList.get(position);
// TODO f.setArguments()
return f;
}
I have main activity and five fragment. In main activity I define toolbar. In each fragment I have a listview with data from JSON (I use volley labrary for fetch data from JSON). 1. I want to filtering data using spinner, i.e with spinner I choose specific "city" and in my listview show only choosen listview items. So how do implement it? 2. All fragments take data from one JSON and there are all show similar data. I want to that when a spinner item seleced from some fragment it influence to other fragment, i.e. if in some fragment chosen "mycity" in other fragment have to show only listview item with "mycity". How to imlement it? I try to do it,but ineffectually. Any ideas, helps are important for me. Sorry for bad English MainActivity
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainactivity);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
//Checkong internet connect
final ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkInfo activeNetwork = conMgr.getActiveNetworkInfo();
if (activeNetwork != null && activeNetwork.isConnected()) {
} else {
Toast.makeText(this, "Проверьте соединение с интернотом" , Toast.LENGTH_LONG).show();
}
}
/**
* Adding fragments to ViewPager
* #param viewPager
*/
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFrag(new MainFragment(),"Все обьявления");
adapter.addFrag(new OneFragment(), "Нужен помощь" );
adapter.addFrag(new TwoFragment(), "Потеряно" );
adapter.addFrag(new ThreeFragment(), "Найдено" );
adapter.addFrag(new FourFragment(), "Отдам даром" );
viewPager.setAdapter(adapter);
}
class ViewPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
}
MainFragment
public class MainFragment extends Fragment {
// Log tag
private static final String TAG = "zhaksyadam";
public static String region="Алматы";
// Movies json url
private static final String url = "http://zhaksy-adam.kz/api/Requisitions/GetRequisition";
private ProgressDialog pDialog;
private List<Movie> movieList = new ArrayList<Movie>();
private ListView listView;
private CustomListAdapter adapter;
Spinner spinner;
public MainFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_one, container, false);
listView = (ListView) rootView.findViewById(R.id.list);
adapter = new CustomListAdapter(getActivity(), movieList);
listView.setAdapter(adapter);
//adding spinner
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayShowCustomEnabled(true);
LayoutInflater inflator = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View vi = inflator.inflate(R.layout.spinnerwound, null);
spinner = (Spinner) vi.findViewById(R.id.spin);
ArrayAdapter<CharSequence> spinneradapter = ArrayAdapter.createFromResource(getActivity(),
R.array.planets_array, R.layout.spinner_item);
spinner.setAdapter(spinneradapter);
((AppCompatActivity)getActivity()).getSupportActionBar().setCustomView(vi);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
region = parent.getItemAtPosition(position).toString();
Log.d(TAG,"MainFragment:"+region);
// Creating volley request obj
final JsonArrayRequest movieReq = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
hidePDialog();
if (movieList != null)
movieList.clear();
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject obj = response.getJSONObject(i);
Movie movie = new Movie();
String city_json = obj.getString("city");
if (region.equals(city_json)) {
String img = obj.getString("Picture1");
if (img != null) {
img = "http://zhaksy-adam.kz" + img;
img = img.replace("~/", "/");
img = img.replace(" ", "%20");
}
String date = obj.getString("Date");
String[] s = date.split("T");
movie.setTitle(obj.getString("Title"));
movie.setThumbnailUrl(img);
movie.setName(obj.getString("FullName"));
movie.setYear(s[0]);
movie.setRegion(obj.getString("region"));
movie.setCity(obj.getString("city"));
movie.setDescription(obj.getString("Description"));
movie.setMobile(obj.getString("Phone1"));
movie.setMail(obj.getString("E_mail"));
movie.setType(obj.getString("type"));
// adding movie to movies array
movieList.add(movie);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifying list adapter about data changes
// so that it renders the list view with updated data
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
AppController.getInstance().addToRequestQueue(movieReq);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
// Showing progress dialog before making http request
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Loading...");
pDialog.show();
return rootView;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onDestroy() {
super.onDestroy();
hidePDialog();
}
private void hidePDialog() {
if (pDialog != null) {
pDialog.dismiss();
pDialog = null;
}
}
}
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've started programming for Android (from iOS), and I working with the boiler plate code that ADT generates for me when I choose Activity+Scrollable tabs option in the new Project wizard. In the code below I've marked the same in comments.
The scenario is I enter text in an editText, press the button and fetch some data from a webservice. I wish to put this data in the appropriate fragment (there are 3 fragments) inside a view pager. I am getting the data and I am able to set it on Fragment 2 and Fragment 3 when I swipe, but the data that is relevant to Fragment 1 is not getting set once the AsycTask is complete. However, after swiping to fragment 3, when I come back to fragment 1, the data is there.
Here is my code:
Activity
public class XXXX extends FragmentActivity {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
//My additions to the boiler plate source generated by ADT
public ArrayList<String> p1T,p2T,p3T,p4T;
private EditText editText;
private Button button;
private boolean flag;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.konjugation);
mSectionsPagerAdapter = new SectionsPagerAdapter (getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
//My additions to the boiler plate source below
flag=false;
p1T = new ArrayList<String>(6);
p2T = new ArrayList<String>(6);
p3T = new ArrayList<String>(6);
p4T = new ArrayList<String>(6);
editText = (EditText) findViewById(R.id.editText1);
button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
String url = editText.getText().toString();
if(!url.isEmpty()) {
url="http://.../?q="+editText.getText().toString();
PAsyncTask task = new PAsyncTask();
task.execute(url);
}
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener(){
#Override
public void onPageSelected(int pos) {
if(flag==true) {
if(pos==0) DummySectionFragment.setText(p4T,p1T);
if(pos==1) DummySectionFragment.setText(p4T,p2T);
if(pos==2) DummySectionFragment.setText(p4T,p3T);
}
else {
Log.d("ts","data not arrived");
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.konjugation, menu);
return true;
}
PagerAdapter
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
Fragment fragment = new DummySectionFragment();
return fragment;
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getString(R.string.title_section1);
case 1:
return getString(R.string.title_section2);
case 2:
return getString(R.string.title_section3);
}
return null;
}
#Override
public void notifyDataSetChanged() {
int pos = mViewPager.getCurrentItem();
if(pos==0) DummySectionFragment.setText(p4T,p1T);
else if(pos==1) DummySectionFragment.setText(p4T,p2T);
else if(pos==2) DummySectionFragment.setText(p4T,p3T);
}
}
AsyncTask
private class PAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params)
{
String response = "";
for (String url : params) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
protected void onPostExecute(String result)
{
try {
p1T.clear();
p2T.clear();
p3T.clear();
//do something very important with the result here
flag=true;
//hoping that somehow the viewpager adapter will refresh the view
mSectionsPagerAdapter.notifyDataSetChanged();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Viewpager's fragment
public static class DummySectionFragment extends Fragment {
private static TextView dummyTextView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_konjugation_dummy, container, false);
dummyTextView = (TextView) rootView.findViewById(R.id.section_label);
return rootView;
}
public static void setText(ArrayList<String> s, ArrayList<String> t) {
try {
DummySectionFragment.dummyTextView.setText("");
for(int i=0;i<s.size();i++) {
DummySectionFragment.dummyTextView.append(s.get(i)+" "+t.get(i)+"\n\n");
}
} catch(NullPointerException e) {
e.printStackTrace();
}
}
}
}
I feel kinda lost, after reading some threads here. Please help :-(
you should update it inside of runOnUiThread() method, which takes a runnable object as argument, so you can pass your implementation in it.