'Android ViewPager and TabLayout are not working fast
There are nested fragments with TabLayout
and ViewPager
. Each fragment has listview inside it so they get call together and now I'm getting an issue of slow processing of app. I have tried some solutions like volley library but it didn't work for me. For more I'm posting my code too so please guide me to make it best.
MainTabFragment.java
public class MainTabFragment extends Fragment {
public static int position_child_tab = 0, three_childs_tab_position = 0;
static int count = -1;
int position_tab = 0;
Bundle args;
MyTabLayout myTabLayout;
public MainTabFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment MainTabFragment.
*/
// TODO: Rename and change types and number of parameters
public static MainTabFragment newInstance(String param1, String param2) {
return new MainTabFragment();
}
@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.main_tab_fragment, container, false);
myTabLayout = (MyTabLayout) view.findViewById(R.id.mainTabLayout);
NonSiwpablePager pager = (NonSiwpablePager) view.findViewById(R.id.pager);
args = getArguments();
if (args != null && args.containsKey("pos_next"))
position_tab = args.getInt("pos_next");
if (args != null && args.containsKey("pos_end"))
position_child_tab = args.getInt("pos_end");
if (position_child_tab != 3) {
three_childs_tab_position = position_child_tab;
} else {
three_childs_tab_position = 0;
}
args = new Bundle();
args.putInt("pos_end", position_child_tab);
ViewPagerAdapter mAdapter = getViewPagerAdapter();
pager.setAdapter(mAdapter);
pager.setOffscreenPageLimit(4);
myTabLayout.setupWithViewPager(pager);
for (int i = 0; i < mAdapter.getCount(); i++) {
View customView = mAdapter.getCustomeView(getActivity(), i);
myTabLayout.getTabAt(i).setCustomView(customView);
}
pager.setCurrentItem(position_tab);
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
myTabLayout.getTabAt(position_tab).getCustomView().setSelected(true);
}
private ViewPagerAdapter getViewPagerAdapter() {
ViewPagerAdapter mAdapter = new ViewPagerAdapter(getChildFragmentManager());
String title_arr[] = {"ADVISORY", "TOP ADVISORS", "EXPERT VIEW"};
for (int i = 0; i < title_arr.length; i++) {
Map<String, Object> map = new Hashtable<>();
map.put(ViewPagerAdapter.KEY_TITLE, title_arr[i]);
if (i == 0) {
map.put(ViewPagerAdapter.KEY_FRAGMENT, AdvisoryPagerFragment.newInstance());
} else if (i == 1) {
map.put(ViewPagerAdapter.KEY_FRAGMENT, TopAdvisoryPagerFragment.newInstance());
} else if (i == 2) {
map.put(ViewPagerAdapter.KEY_FRAGMENT, ExperViewPagerFragment.newInstance());
}
mAdapter.addFragmentAndTitle(map);
}
return mAdapter;
}
public static class ViewPagerAdapter extends FragmentStatePagerAdapter {
private static final String KEY_TITLE = "fragment_title";
private static final String KEY_FRAGMENT = "fragment";
boolean abc = false;
private int[] drawables = new int[]{R.drawable.advisory_selector, R.drawable.top_advisors_selector, R.drawable.expertview_selector};
private List<Map<String, Object>> maps = new ArrayList<>();
public ViewPagerAdapter(FragmentManager fm) {
super(fm);
}
public View getCustomeView(Context context, int pos) {
View mView = LayoutInflater.from(context).inflate(R.layout.custom_tab_view, null);
TextView mTextView = (TextView) mView.findViewById(R.id.textView);
mTextView.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/ufonts.com_cambria.ttf"));
ImageView mImageView = (ImageView) mView.findViewById(R.id.imageView2);
mImageView.setTag(pos);
/*if(count >0)
{
Toast.makeText(context,"Count Is "+count,Toast.LENGTH_SHORT).show();
mImageView = (ImageView) mImageView.getTag(0);
mImageView.setSelected(false);
}
*/
mImageView.setImageResource(drawables[pos]);
mTextView.setText(getPageTitle(pos));
return mView;
}
public void addFragmentAndTitle(Map<String, Object> map) {
maps.add(map);
}
@Override
public CharSequence getPageTitle(int position) {
return (CharSequence) maps.get(position).get(KEY_TITLE);
}
@Override
public Fragment getItem(int position) {
return (Fragment) maps.get(position).get(KEY_FRAGMENT);
}
@Override
public int getCount() {
return maps.size();
}
}
}
Child Fragment of MainTabFragment
is as :
AdvisoryPagerFragment.java
public class AdvisoryPagerFragment extends Fragment {
static String advisory_child_fragments[];
int myID = 0;
Bundle bundle;
TabLayout mTabLayout;
public AdvisoryPagerFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @return A new instance of fragment AdvisoryPagerFragment.
*/
public static AdvisoryPagerFragment newInstance() {
return new AdvisoryPagerFragment();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View inflate = inflater.inflate(R.layout.fragment_app_pager, container, false);
/*Bundle args = getArguments();
if (args != null && args.containsKey("pos_end"))
myID = args.getInt("pos_end");*/
myID = MainTabFragment.position_child_tab;
mTabLayout = (TabLayout) inflate.findViewById(R.id.fragmentTabLayout);
advisory_child_fragments = new String[]{"EQUITY", "INDICES", "COMMODITY", "CURRENCY"};
ViewPager pager = (ViewPager) inflate.findViewById(R.id.fragment_pager);
FragmentViewPagerAdapter mPagerAdapter = new FragmentViewPagerAdapter(getChildFragmentManager());
pager.setAdapter(mPagerAdapter);
mTabLayout.setupWithViewPager(pager);
for (int i = 0; i < mPagerAdapter.getCount(); i++) {
View customView = mPagerAdapter.getCustomeView(getActivity(), i);
mTabLayout.getTabAt(i).setCustomView(customView);
}
pager.setCurrentItem(myID);
return inflate;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mTabLayout.getTabAt(myID).getCustomView().setSelected(true);
}
public static class FragmentViewPagerAdapter extends FragmentStatePagerAdapter {
public FragmentViewPagerAdapter(FragmentManager fm) {
super(fm);
}
public View getCustomeView(Context context, int pos) {
View mView = LayoutInflater.from(context).inflate(R.layout.custom_view, null);
TextView mTextView = (TextView) mView.findViewById(R.id.belowTab_textview);
mTextView.setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/ufonts.com_cambria.ttf"));
mTextView.setText(getPageTitle(pos));
return mView;
}
//
@Override
public CharSequence getPageTitle(int position) {
return advisory_child_fragments[position];
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new EquityFragment();
case 1:
return new IndicesFragment();
case 2:
return new CommodityFragment();
case 3:
return new CurrencyFragment();
}
return null;
}
@Override
public int getCount() {
return 4;
}
}
}
And the child fragment of above AdvisoryPagerFragment
is
EquityFragment.java
public class EquityFragment extends android.support.v4.app.Fragment implements SearchView.OnQueryTextListener {
public static String imagepath = null;
static ArrayList<EquityDetails> catListDao = new ArrayList<EquityDetails>();
static ArrayList<EquityDetails> catListDao1 = new ArrayList<EquityDetails>();
static int count = 0;
static int count1 = 0;
ListView list;
View view;
Activity act;
AdvisorsAdapter adapter;
TextView empty_text;
private boolean isViewShown = false;
ProgressBar progressBar;
public static EquityFragment newInstance() {
return new EquityFragment();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.equity_activity, container, false);
act = this.getActivity();
Log.d("Callled ", "" + count);
count++;
return view;
}
public void onActivityCreated(Bundle savedInstanceState1) {
super.onActivityCreated(savedInstanceState1);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
list = (ListView) view.findViewById(R.id.list_equity);
setHasOptionsMenu(true);
empty_text = (TextView) view.findViewById(R.id.empty);
progressBar = (ProgressBar) view.findViewById(R.id.progressBar);
if (Utils.isNetworkAvailable(getActivity())) {
if (catListDao.size() > 0) {
adapter = new AdvisorsAdapter(act, R.layout.custom_equity, catListDao, 5);
list.setAdapter(adapter);
} else {
new Thread(new Runnable() {
@Override
public void run() {
// do some work here
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// if (!isViewShown) {
new FetchAllData(getActivity(), 5).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
// }
}
});
}
}).start();
}
} else {
CustomToast toast = new CustomToast(getActivity(), "There is no internet connection!");
}
}
FetchdataClass
which fetches the data from service and add into ListView
public class FetchAllData extends AsyncTask<Void, Void, String> {
ProgressDialog pDialog;
int typeId;
private Context cont;
public FetchAllData(Context con, int typeId) {
// TODO Auto-generated constructor stub
this.cont = con;
this.typeId = typeId;
Log.d("Constructor Called", "yes");
}
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected String doInBackground(Void... params) {
// TODO Auto-generated method stub
return getString();
}
private String getString() {
// TODO Auto-generated method stub
URL obj = null;
HttpURLConnection con = null;
try {
obj = new URL(Constants.AppBaseUrl + "/call_listing/" + typeId);
String userPassword = "oi" + ":" + "kl";
String header = "Basic " + new String(android.util.Base64.encode(userPassword.getBytes(), android.util.Base64.NO_WRAP));
con = (HttpURLConnection) obj.openConnection();
con.addRequestProperty("Authorization", header);
con.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
con.setRequestMethod("POST");
// For POST only - BEGIN
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.flush();
os.close();
// For POST only - END
int responseCode = con.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) { //success
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
Log.i("TAG", response.toString());
return response.toString();
} else {
Log.i("TAG", "POST request did not work.");
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
if (result != null) {
// pDialog.dismiss();
progressBar.setVisibility(View.GONE);
JSONObject jsonObject;
try {
catListDao = new ArrayList<EquityDetails>();
jsonObject = new JSONObject(result);
JSONArray jsonArray = jsonObject.getJSONArray("list");
Log.d("Length ", "" + jsonArray.length());
for (int i = 0; i < jsonArray.length(); i++) {
EquityDetails allDirectory = new EquityDetails();
allDirectory.setEntry_value(jsonArray.getJSONObject(i).getString("entry"));
allDirectory.setSerial_value(jsonArray.getJSONObject(i).getString("sl"));
allDirectory.setTg_value1(jsonArray.getJSONObject(i).getString("tgt_1"));
allDirectory.setTg_value2(jsonArray.getJSONObject(i).getString("tgt_2"));
allDirectory.setMainTitle_value(jsonArray.getJSONObject(i).getString("script"));
allDirectory.setMain_subTitle_value(jsonArray.getJSONObject(i).getString("exchange"));
allDirectory.setRating_value(jsonArray.getJSONObject(i).getString("rating"));
allDirectory.setReview_value(jsonArray.getJSONObject(i).getString("review"));
allDirectory.setImage1(jsonArray.getJSONObject(i).getString("advisor_image"));
allDirectory.setPosted_by(jsonArray.getJSONObject(i).getString("posted_by"));
allDirectory.setImage2(jsonArray.getJSONObject(i).getString("script_image"));
allDirectory.setCall_id(jsonArray.getJSONObject(i).getString("call_id"));
allDirectory.setBuy(jsonArray.getJSONObject(i).getString("buy_sentiment"));
allDirectory.setSell(jsonArray.getJSONObject(i).getString("sell_sentiment"));
allDirectory.setRecommend(jsonArray.getJSONObject(i).getString("recommendation"));
allDirectory.setPosted_date(jsonArray.getJSONObject(i).getString("posted_date"));
allDirectory.setExpiry_date(jsonArray.getJSONObject(i).getString("expiry_date"));
catListDao.add(allDirectory);
}
catListDao1 = catListDao;
ab = true;
adapter = new AdvisorsAdapter(act, R.layout.custom_equity, catListDao, 0);
list.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
//pDialog.dismiss();
progressBar.setVisibility(View.GONE);
}
}
Solution 1:[1]
try to set
pager.setOffscreenPageLimit(no_of_fragments or pages);
Do all your task in asyctask on creation of fragments
Solution 2:[2]
I will suggest you to add the another method.
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if (menuVisible) {
Log.e("SetMenuVisibleFragmentA" , menuVisible + " ");
}
}
public void setMenuVisibility (boolean menuVisible)
Set a hint for whether this fragment's menu should be visible. This is useful if you know that a fragment has been placed in your view hierarchy so that the user can not currently seen it, so any menu items it has should also not be shown.
Parameters
menuVisible :: The default is true, meaning the fragment's menu will be shown as usual. If false, the user will not see the menu.
Solution 3:[3]
Your
onActivityCreated(Bundle savedInstanceState1)"
in EquityFragment.java is weird. First of all, don't deactivate the StrictMode (because you ignore the thrown "NetworkOnMainThread" Exception which is most likely the reason for your code to be slow...)
Then look at the else Part:
} else {
new Thread(new Runnable() {
@Override
public void run() {
// do some work here
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
// if (!isViewShown) {
new FetchAllData(getActivity(), 5).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
// }
}
});
}
}).start();
}
You start a new Thread, where you should do your network stuff. Instead of doing it, you return to the ui thread (if you do network stuff here the app will hang") in your new thread and do it on the ui thread. (I don't know what exactly FetchAllData does).
} else {
new FetchAllData(getActivity(), 5).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
should do the same Job.
In your FetchAllData class, you do all the JSON parsing in onPostExecute. Do the parsing in doInBackground and only set the adapter in onPostExecute.
Solution 4:[4]
It seems that you do too much work in onPostExecute method. Try to parse JSON and set data in background and notify the change in UIthread may be workable.
Solution 5:[5]
Move the code from
OnActivityCreated()
toonViewCreated()
.Use
Gson
if Possible.(It had saved valuable seconds in my project.)Post your adapters code if possible. If you are doing too many operation in
getView()
avoid it.In your AsyncTask, you are using UI elements. I know we can access UI components in
onPostExecute()
, but try ro run that code on UI thread by usingrunOnUIThread()
. It improves performance.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Kaushik |
Solution 2 | curiousMind |
Solution 3 | |
Solution 4 | ??? |
Solution 5 | TheAndroidFreak |