ViewPagerIndicator with two ListFragment slow when loading data - android

I have an app with ViewPager and ViewPagerIndicator. I have two tabs made ​​with TabPageIndicator. Each tab loads a listivew with data of Internet. When I run the app loads the data from tab 1 and 2, this causes very slow to show the view.
I want that when I started my app only load data tab 1 and when I move or click on tab 2 load the data for that tab.
Can you help me?
Thank you.
My code:
MainActivity
public class MainActivity extends FragmentActivity {
private static final String[] CONTENT = new String[] { "Releases", "Artists" };
private ListView listRls;
private List<Fragment> listaFragments;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
listaFragments = new ArrayList<Fragment>();
listaFragments.add(new FragmRls());
listaFragments.add(new FragmArt());
MyFragmentAdapter adapter = new MyFragmentAdapter(getSupportFragmentManager(),
listaFragments);
ViewPager pager = (ViewPager)findViewById(R.id.pager);
pager.setAdapter(adapter);
TabPageIndicator indicator = (TabPageIndicator)findViewById(R.id.indicator);
indicator.setViewPager(pager);
}
class MyFragmentAdapter extends FragmentStatePagerAdapter {
//Implementacion del fragmentStateADapter
private List<Fragment> fragments;
public MyFragmentAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
// TODO Auto-generated constructor stub
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
// TODO Auto-generated method stub
return fragments.get(position);
}
#Override
public CharSequence getPageTitle(int position) {
return CONTENT[position % CONTENT.length].toUpperCase();
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return fragments.size();
}
}//fin adapter
}//fin class
Code in one of the classes that extend from ListFragement, the other is identical.
public class FragmRls extends ListFragment{
JSONParser jParser = new JSONParser();
private static String url_all_post = "http://adeptlabel.com/listReleaseforTab.php";
private static String url_all_art = "http://adeptlabel.com/listArtists.php";
private static final String TAG_SUCCESS = "success";
private static final String TAG_posts = "wp_posts";
private static final String TAG_TITULO = "titulo";
private static final String TAG_IMAGEN = "imagen";
JSONArray posts = null;
private ArrayList <ElementosList> elementos = new ArrayList <ElementosList>();
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
return inflater.inflate(R.layout.fragmrls, null);
}//Fin On CreateView
#Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
elementos.clear();
loadDataJsonRls();
for(int i=0;i<ListViewConfig.getResim_list_txt().size();i++)
{
elementos.add(new ElementosList(ListViewConfig.getResim_list_txt().get(i),
ListViewConfig.getResim_list_img().get(i)));
}
ArrayAdapter<ElementosList>adaptador = new AdaptadorList(getActivity(),elementos);
setListAdapter(adaptador);
}
public void loadDataJsonRls()
{
List<NameValuePair> params = new ArrayList<NameValuePair>();
// getting JSON string from URL
JSONObject json = jParser.makeHttpRequest(url_all_post, "GET", params);
// Check your log cat for JSON reponse
Log.d("All releases: ", json.toString());
try {
// Checking for SUCCESS TAG
int success = json.getInt(TAG_SUCCESS);
if (success == 1) {
posts = json.getJSONArray(TAG_posts);
//Borramos los arrayList
ListViewConfig.deleteResim_list_img();
ListViewConfig.deleteResim_list_txt();
// looping through All post
for (int i = 0; i < posts.length(); i++) {
boolean repite = false;
JSONObject c = posts.getJSONObject(i);
// Storing each json item in variable
String titulo = c.getString(TAG_TITULO);
String imagen = c.getString(TAG_IMAGEN);
for(int j=0;j<ListViewConfig.getResim_list_txt().size();j++)
{
if(titulo.equals(ListViewConfig.getResim_list_txt().get(j)))
{
repite = true;
}
}
if(repite==false)
{
ListViewConfig.addImageUrls(imagen);
ListViewConfig.addTextUrls(titulo);
}
}
} else {
//Log.d("MainActivity.class", "No success Json");
}
} catch (JSONException e) {
e.printStackTrace();
}
}//fin cargarDatosJsonRls()
}//fin class

If you want to load data associated with second tab when user switch to that tab, try to move code that loads data from onCreate to a public method. Then set OnPageChangeListener and load data when onPageSelected is called.
Furthermore, make sure that you load data asynchronously, for example using AsyncTask.

You are making your network calls on the UI thread, this is why your UI is slow. You may want to use an AsyncTask, effectively moving your network activity to another thread. Its doInBackground method will handle the network things, and the onPostExecute method allows you to update your UI when the execution of the Task is finished. More details in the official documentation here.
Additionally, depending on your needs and time, you could either pre-load the data so the loading time when the user is presented with the screen is reduced, or show a ProgressBar while you are loading the data, then update the UI when loading is done.

The solution to my problem I found here:
(ViewPager, ListView, and AsyncTask, first page blank, all data in the second page
However, thanks for your attention Nartus and 2Dee.

Related

How to parse JSON to viewpager

I am a beginner at the android studio. I have parsed some JSON data from the server. I want to implement these data in a viewpager. I got A sample viewpager code. But when I apply these JSON data to list it shows cannot resolve constructor. My Viewpager code is below.
My JSON Fetching code
public class MainActivity extends AppCompatActivity {
// Constants
private static final String TAG = MainActivity.class.getSimpleName();
// UI Components
private VerticalViewPager mVvpMainPager;
// Other objects
private ViewPagerAdapter mPagerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mVvpMainPager = findViewById(R.id.activity_main_vvp_main_pager);
setupViewPager();
}
private void setupViewPager() {
mPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
for (BeanNews news : generateSampleNewsData()) {
mPagerAdapter.addFragment(PagerFragment.newInstance(news), "News " + news.getNewsId());
}
mVvpMainPager.setAdapter(mPagerAdapter);
mVvpMainPager.setOffscreenPageLimit(generateSampleNewsData().size());
}
private ArrayList<BeanNews> generateSampleNewsData() {
String url ="http://maranamassapp.cf/json_getdata.php";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("server_response");
for(int i = 0; i < jsonArray.length(); i++){
JSONObject ser =jsonArray.getJSONObject(i);
String creatorname = ser.getString("head");
String imageUrl = ser.getString("image");
String cat = ser.getString("content");
String postdate = ser.getString("weburl");
String dateall = ser.getString("date");
BeanNews news = new BeanNews(creatorname,imageUrl,cat,postdate,dateall);
ArrayList<BeanNews> newsList = new ArrayList<>();
newsList.add(news);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
});
return newsList;
}
Check this about ViewPager:
Layout manager that allows the user to flip left and right through
pages of data. You supply an implementation of a PagerAdapter to
generate the pages that the view shows.
ViewPager is most often used in conjunction with Fragment, which is a
convenient way to supply and manage the lifecycle of each page.
Now, you'll need a RecyclerView or a ListView inside ViewPager xml layout file to show the data. So, you'll need Fragment inside ViewPager, a RecyclerView || ListView inside Fragment then showing data or adding to RecyclerView adapter.
Can't actually pass list of items(from json in your case) to ViewPager to show on the view in Android.

Unable to design viewpager in the layout with dynamic data

I'm new in android and want an app with viewpager. I am unable to design the viewpager in the layout. The layout fetch the data dynamatically. I want to create a matreial UI viewpager which swipes the page left or right like a paper.I have made a view which shows the data but is unable to swipe like a viewpager left or right...
The code is as below:
public class DetailNewsActivity extends AppCompatActivity {
private PullToZoomScrollViewEx scrollView;
private ArrayList<NewsItemModel> newsArr;
private TextView tvNewsTitle;
private TextView tvNewsPublishDate;
private TextView tvNewsFull;
private int newsPosition = 0;
private ImageView ivYoutubeEnable;
private SharedPreferences sharedPref;
int textSize = 16;
boolean isHighQuality = false;
private Typeface typeface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail_news);
init();
AdView mAdView = (AdView) findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice("5745FD6726ACCBEE8324DB158D021FA5")
.build();
mAdView.loadAd(adRequest);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_detail_news, container, false);
return view;
}
private void init() {
typeface = Typeface.createFromAsset(getAssets(), "AnmolUni.ttf");
// newsArr = (ArrayList<NewsItemModel>) getIntent().getSerializableExtra("newsArray");
newsArr = AppController.getAppController().getMainNewsArr();
AppController.getAppController().setMainNewsArr(null);
newsPosition = getIntent().getIntExtra("newsPosition", 0);
findViewById(R.id.iv_back).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
findViewById(R.id.iv_share).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
generateBranchURL(newsPosition);
}
});
sharedPref = getSharedPreferences(Constants.SHARED_PREF_NAME, Context.MODE_PRIVATE);
textSize = sharedPref.getInt("text_size", 16);
isHighQuality = sharedPref.getBoolean("isHighQuality",false);
loadViewForCode();
scrollView = (PullToZoomScrollViewEx) findViewById(R.id.scroll_view);
setNewsFromArray(newsPosition);
// ((ImageView) scrollView.getZoomView().findViewById(R.id.iv_zoom)).setImageResource(android.R.drawable.arrow_down_float);
(scrollView.getZoomView().findViewById(R.id.iv_zoom)).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(DetailNewsActivity.this, ImageVideoActivity.class);
intent.putExtra("viewType", "image");
if(isHighQuality)
intent.putExtra("imageArr", newsArr.get(newsPosition).getImage());
else
intent.putExtra("imageArr", newsArr.get(newsPosition).getMedium());
startActivity(intent);
}
});
DisplayMetrics localDisplayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(localDisplayMetrics);
int mScreenHeight = localDisplayMetrics.heightPixels;
int mScreenWidth = localDisplayMetrics.widthPixels;
LinearLayout.LayoutParams localObject = new LinearLayout.LayoutParams(mScreenWidth, (int) (9.0F * (mScreenWidth / 16.0F)));
scrollView.setHeaderLayoutParams(localObject);
scrollView.setParallax(true);
// scrollView.getPullRootView().findViewById(R.id.container_layout).setOnTouchListener(new OnSwipeTouchListener(DetailNewsActivity.this) {
scrollView.getPullRootView().setOnTouchListener(new OnSwipeTouchListener(DetailNewsActivity.this) {
#Override
public void onSwipeLeft() {
if (newsPosition < newsArr.size() - 1) {
newsPosition++;
setNewsFromArray(newsPosition);
} else {
CommonUtils.showToast(DetailNewsActivity.this, "No more news");
}
}
#Override
public void onSwipeRight() {
if (newsPosition > 0) {
newsPosition--;
setNewsFromArray(newsPosition);
} else {
CommonUtils.showToast(DetailNewsActivity.this, "This is the first news");
}
}
});
scrollView.setOnPullZoomListener(new PullToZoomBase.OnPullZoomListener() {
#Override
public void onPullZooming(int newScrollValue) {
Log.d("MainActivity", "onPullZooming: " + newScrollValue);
// Intent intent = new Intent(DetailNewsActivity.this, ImageVideoActivity.class);
// intent.putExtra("viewType", "image");
// intent.putExtra("imageArr", newsArr.get(newsPosition).getImage());
// startActivity(intent);
}
#Override
public void onPullZoomEnd() {
}
});
}
void setNewsFromArray(int position) {
if (position >= newsArr.size()) {
finish();
return;
}
if (!newsArr.get(position).getMedium().get(0).isEmpty()) {
if(isHighQuality)
Picasso.with(DetailNewsActivity.this).load(newsArr.get(position).getImage().get(0)).placeholder(R.drawable.logo).error(R.drawable.logo).
into((ImageView) scrollView.getZoomView().findViewById(R.id.iv_zoom));
else
Picasso.with(DetailNewsActivity.this).load(newsArr.get(position).getMedium().get(0)).placeholder(R.drawable.logo).error(R.drawable.logo).
into((ImageView) scrollView.getZoomView().findViewById(R.id.iv_zoom));
} else {
((ImageView) scrollView.getZoomView().findViewById(R.id.iv_zoom)).setImageResource(R.drawable.logo);
}
tvNewsTitle.setText(newsArr.get(position).getTitle());
tvNewsPublishDate.setText(newsArr.get(position).getPublish_dt());
//String style = "<html><body style='text-align:justify'>";
//Log.i("RAJEEV",style + newsArr.get(position).getFullnews());
tvNewsFull.setText(Html.fromHtml( newsArr.get(position).getFullnews()));
if (newsArr.get(position).getYoutube_video().isEmpty()) {
ivYoutubeEnable.setVisibility(View.GONE);
} else {
ivYoutubeEnable.setVisibility(View.VISIBLE);
}
ivYoutubeEnable.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(DetailNewsActivity.this, ImageVideoActivity.class);
intent.putExtra("viewType", "youtube");
intent.putExtra("youtube_code", newsArr.get(newsPosition).getYoutube_video());
startActivity(intent);
}
});
}
private void loadViewForCode() {
PullToZoomScrollViewEx scrollView = (PullToZoomScrollViewEx) findViewById(R.id.scroll_view);
View headView = LayoutInflater.from(this).inflate(R.layout.ptz_head_view, null, false);
View zoomView = LayoutInflater.from(this).inflate(R.layout.ptz_zoom_view, null, false);
View contentView = LayoutInflater.from(this).inflate(R.layout.ptz_content_view, null, false);
scrollView.setHeaderView(headView);
scrollView.setZoomView(zoomView);
scrollView.setScrollContentView(contentView);
tvNewsTitle = (TextView) scrollView.getPullRootView().findViewById(R.id.tv_news_title);
tvNewsPublishDate = (TextView) scrollView.getPullRootView().findViewById(R.id.tv_news_publish_date);
tvNewsFull = (TextView) scrollView.getPullRootView().findViewById(R.id.tv_news_full);
tvNewsFull.setTextSize(textSize);
if (!AppController.isPunjabiSupported()) {
tvNewsTitle.setTypeface(typeface);
tvNewsFull.setTypeface(typeface);
}
ivYoutubeEnable = (ImageView) scrollView.getHeaderView().findViewById(R.id.iv_youtube_header);
}
void generateBranchURL(final int newsPosition) {
// String imageUrl = "";
// if (newsArr.get(newsPosition).getMedium().size() <= 1)
// imageUrl = newsArr.get(newsPosition).getMedium().get(0);
BranchUniversalObject branchUniversalObject = new BranchUniversalObject()
.setCanonicalIdentifier("NewsDetails")
///.setCanonicalUrl("https://branch.io/deepviews")
//.setTitle("" + newsArr.get(newsPosition).getTitle())
//.setContentDescription("" + newsArr.get(newsPosition).getIntro())
//.setContentImageUrl("" + imageUrl)
// You use this to specify whether this content can be discovered publicly - default is public
.setContentIndexingMode(BranchUniversalObject.CONTENT_INDEX_MODE.PUBLIC);
// Here is where you can add custom keys/values to the deep link data
//.addContentMetadata("property1", "blue")
//.addContentMetadata("property2", "red");
LinkProperties linkProperties = new LinkProperties()
.addControlParameter("$desktop_url", "http://www.newsnumber.com/news/share/" + newsArr.get(newsPosition).getFn_id())
.addControlParameter("$ios_url", "itms-apps://itunes.apple.com/us/app/newsnumber/id1022442357?mt=8")
.addControlParameter("NewsId", "" + newsArr.get(newsPosition).getFn_id())
.addControlParameter("CatId", "" + newsArr.get(newsPosition).getCat_id())
.addControlParameter("$og_title", newsArr.get(newsPosition).getTitle())
.addControlParameter("$og_description", newsArr.get(newsPosition).getIntro())
.addControlParameter("$og_image_url", newsArr.get(newsPosition).getImage().get(0))
.addControlParameter("$twitter_title", newsArr.get(newsPosition).getTitle())
.addControlParameter("$twitter_description", newsArr.get(newsPosition).getIntro())
.addControlParameter("$twitter_image_url", newsArr.get(newsPosition).getImage().get(0))
;
branchUniversalObject.generateShortUrl(this, linkProperties, new Branch.BranchLinkCreateListener() {
#Override
public void onLinkCreate(String url, BranchError error) {
if (error == null) {
Log.i("MyApp", "got my Branch link to share: " + url);
Intent sharingIntent = new Intent(Intent.ACTION_SEND);
sharingIntent.setType("text/plain");
sharingIntent.putExtra(Intent.EXTRA_SUBJECT, "News Number\n");
sharingIntent.putExtra(Intent.EXTRA_TEXT, url);
startActivity(Intent.createChooser(sharingIntent, "Share via"));
}
}
});
}
}
can anyone help??
thanks in advance.
It seems like you might be trying to make a new Activity for each "page" of a ViewPager. The Android support library already has their own ViewPager that uses fragments.
You basically need three things to use a ViewPager:
The ViewPager itself
An adapter for the ViewPager
The fragment that will be used in the ViewPager (esentially the "template" that will be used for each "page" in the ViewPager)
First, we'll create the fragment. This is just a simple example that uses only one TextView, but it will work for any amount of views and data. You'll notice that static method "newInstance()" that creates and returns an instance of this fragment. Google recommends using this method to instantiate new Fragments for a ViewPager as it makes passing data to the fragment much easier. All fragments have a "setArguments()" method that lets you pass in a Bundle when you instantiate it with whatever data you want. The method "getArguments()" can be used to access that bundle and get the values out of it in onCreate() or onCreateView(). This is how you pass in an object or objects to bind its data to the views. In this example, were just passing in a String and setting that String to a TextView. You'll see how it's used when we create the adapter for the ViewPager.
//You should be using android.support.v4.app.Fragment here
public class ExampleFragment extends Fragment {
private static final String DAY_NAME_KEY = "day_name";
private TextView dayName;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.fragment_example, container, false);
dayName = (TextView) fragmentView.findViewById(R.id.day_name);
return fragmentView;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//Set the name of the day to the dayName TextView
String day = getArguments().getString(DAY_NAME_KEY);
dayName.setText(day);
}
public static ExampleFragment newInstance(String day) {
Bundle bundle = new Bundle();
bundle.putString(DAY_NAME_KEY, day);
ExampleFragment fragment = new ExampleFragment();
fragment.setArguments(bundle);
return fragment;
}
}
Now, we need to make an adapter that will create the views when the ViewPager is swiped. You need to extend either FragmentPagerAdapter or FragmentStatePagerAdapter. FragmentPagerAdapter is used for a small number of static fragments and it will use more memory. So you only want to use this if you have 4 or 5 pages and aren't adding any more dynamically.
For your case, it sounds like you want to swipe through a variable number of pages that are dynamically added, so you want to use FragmentStatePagerAdapter. It's optimized for memory efficiency and it will handle the saving and restoring of the fragments' state for you.
The adapter is simple.
First, you need to make your constructor match the super class's constructor. What that means is that your constructor must have a FragmentManager parameter. All you do with that is pass it to the super class. (You'll see below.)
Secondly, you have to implement just 2 methods from the FragmentStatePagerAdapter class:
public Fragment getItem(int position)
and
public int getCount()
getItem will be automatically called by the ViewPager when it is swiped. You just have to tell it what type of fragment to return. We'll be using the newInstance() method from the ExampleFragment class here.
getCount is the number of views that your ViewPager will be using. For example, I will have an ArrayList that will contain 7 strings (one for each day of the week). I want each one of those strings to be displayed on a different page of my ViewPager. So I'm just going to return the size of the ArrayList for this method.
Here's the class:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
//A reference to the array of data that will be used to populate
//each fragment. In this case it's an array of Strings, but it
//could be any type of object. The Strings within this array are what
//we'll be passing to the newInstance() method of each fragment.
private ArrayList<String> days;
//Constructor must take a FragmentManager to match the superclass.
public ViewPagerAdapter(FragmentManager fm, ArrayList<String> days) {
//All you have to do with the fragment manager is pass it to super
super(fm);
//The array will be passed in when we create the Adapter in our Activity
this.days = days;
}
#Override
public Fragment getItem(int position) {
/*
Automatically called when another page is needed.
The adapter will keep track of the position of the current page
so the first time this is called, it will be 0, then when a
swipe occurs, it will be one. If it is swiped backward, it will go back to 0.
So when the position is 0, a new Fragment will be created and the
String at days.get(0) ("Monday") will be passed to it.
*/
return ExampleFragment.newInstance(days.get(position));
}
#Override
public int getCount() {
return days.size();
}
}
Now we just have to set the adapter for the ViewPager in our Activity and it will automatically handle swipes for us.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ArrayList<String> daysOfWeek = new ArrayList<>();
daysOfWeek.add("Monday");
daysOfWeek.add("Tuesday");
daysOfWeek.add("Wednesday");
daysOfWeek.add("Thursday");
daysOfWeek.add("Friday");
daysOfWeek.add("Saturday");
daysOfWeek.add("Sunday");
ViewPager pager = findViewById(R.id.view_pager);
//Pass the activity's fragmentmanager by calling getSupportFragmentManager().
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager(), daysOfWeek);
pager.setAdapter(adapter);
}
}
This is what we get (I've added some padding and color to make it clear):
As for changing the way the pages "turn" (for example, like a newspaper), you need to look into PageTransformer

Complications with Viewpager [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am using a ViewPager and have 3 Fragments in it.
I know that when the ViewPager loads for the first time it loads all the fragments by default ,
minimum is 3 fragments and viewpager executes all the lifecycle methods of fragments.
Problems I noticed :
Whenever I swipe the viewpager the selected fragment doesn't call any of its lifecycle methods again.
Hence I cannot access the global variables directly.
e.g: if I have a preference initialized in OnCreateView() I am getting NPE when I try to access it from activity by initializing the instance of that fragment and calling a method in that fragment.
Also not even onResume is getting called for any fragment after first loading.
What I want to Know :
How can I access the views and preferences after I have already initialized them in onCreateView() ?
But for the button which is initialized in onCreateView(), on click of it calls the web-services and works perfectly as I want .How ?
I have stuck with these issues from the past 3 days and googled a lot but not found my answers.
Any Help will be appreciated.
Fragment Code :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_dth, container, false);
preferences=
PreferenceManager.getDefaultSharedPreferences(getActivity());
editor = preferences.edit();
editAmt = (EditText) v.findViewById(R.id.editAmt);
browsplan = (Button) v.findViewById(R.id.browsplan);
Log.e("DTH onCreateView ",""+page);
String fontpath = "fonts/OpenSans-Regular.ttf";
Typeface tf = Typeface.createFromAsset(getActivity().getAssets(),
fontpath);
editCustomerid.setTypeface(tf);
editAmt.setTypeface(tf);
token=preferences.getString("Token","-1");
mobileNo=preferences.getString("userMobileNo","0");
browsplan.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//new DTHOperator(getActivity()).execute(); HERE IT WORKS PROPERLY
}
});
return v;
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser && isResumed()){
new DTHOperator(getActivity()).execute();
Toast.makeText(getActivity(),"setUserVisibleHint DTH "
,Toast.LENGTH_SHORT).show();
}
}
public class DTHOperator extends AsyncTask<Context, Integer, String> {
Context ctx;
DTHOperator(Context ctx) {
this.ctx = ctx;
}
#Override
protected String doInBackground(Context... params) {
List<NameValuePair> telecomdata = new ArrayList<NameValuePair>();
String result;
Log.d("Register Activity Token", /*preferences.getString("Token", "")*/token);
telecomdata.add(new BasicNameValuePair("mobNo", /*preferences.getString("userMobileNo", "")*/mobileNo));
telecomdata.add(new BasicNameValuePair("requestDate", Utilities.getApiCallTimeFormat()));
telecomdata.add(new BasicNameValuePair("reqFrom", "APP"));
Log.v("PostParameters", "telecomdata" + telecomdata);
if (Connectivity.checkNetwork(ctx)) {
result = rechargeUrl.queryRESTurlONline(ctx, "/GetDTHOperatorsService", "post", telecomdata, GenericConstants.PiPay_root);
} else {
result = GenericConstants.NETWORKNOTFOUND;
displayToast("The Internet Connection appears to be offline");
}
return result;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
MyProgress.show(ctx, "", "");
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
if (result != null) {
if (result.equalsIgnoreCase(GenericConstants.NETWORKNOTFOUND)) {
MyProgress.CancelDialog();
Toast.makeText(ctx,"The Internet Connection appears to be offline",Toast.LENGTH_SHORT).show();
return;
}
String[] resArr = result.split("delimiter_");
if (!resArr[0].equals("500")) {
MyProgress.CancelDialog();
Log.d("DTHOperator Response ::", result);
JSONArray jsonArray = null;
JSONObject object = new JSONObject(result);
jsonArray = object.getJSONArray("data");
for (int i = 0; i < jsonArray.length(); i++) {
if (jsonArray.getJSONObject(i).has("opName")) {
operator.add(jsonArray.getJSONObject(i).getString("opName"));
Log.d("", " Question size " + operator.size());
}
}
if(MyProgress.isShowingProgress())
MyProgress.CancelDialog();
editAmt.setText("2000"); // NPE HERE Also setting the value
} else {
MyProgress.CancelDialog();
displayToast("Failure");
}
}
} catch (Exception e) {
e.printStackTrace();
MyProgress.CancelDialog();
}finally {
if(MyProgress.isShowingProgress())
MyProgress.CancelDialog();
}
}
Use the following override method
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser && isResumed()) {
}
}
this will give you an option to call anything when the the user is currently viewing the fragment.
Set a hint to the system about whether this fragment's UI is currently visible * to the user. This hint defaults to true and is persistent across fragment instance* state save and restore.
An app may set this to false to indicate that the fragment's UI is
scrolled out of visibility or is otherwise not directly visible to the user.
This may be used by the system to prioritize operations such as fragment lifecycle updates
or loader ordering behavior.
*
#param isVisibleToUser true if this fragment's UI is currently visible to the user (default),
false if it is not.
You can keep instances of Fragments which you use in your ViewPager. Here's an example:
In your ViewPagerAdapter define a SparseArray and override the methods like below:
SparseArray<Fragment> registeredFragments = new SparseArray<>();
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
And add a PageChangeListener to your ViewPager:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
// Here's your fragment instance
// You can access it's methods, variables, views etc.
YourFragment fragment =(YourFragment)yourPagerAdapter.getRegisteredFragment(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
I hope this'll help you. Good luck!
Edit:
You can define your Fragment's Views public or define a getter method for your view and access from your fragment instance such as:
public TextView mTextView;
or
private TextView mTextVieW;
public TextView getTextView(){
return this.mTextView;
}
You can access it like below:
TextView textView = yourFragmentInstance.mTetxView;
or
TextView textview = yourFragmentInstance.getTextView();
This worked for me in my last project. I like this approach too because I don't have to do anything weird.
Essentially, in my adapter for the viewpager I added a method to keep track of the fragment tags & the associated position.
public class TabAdapter extends FragmentPagerAdapter {
private Map<Integer, String> tagMap = new HashMap<>(2); // matches tab count
public TabAdapter(FragmentManager fMgr) {
super(fMgr);
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!
// Capturing the tag that is auto-generated
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment frag = (Fragment) super.instantiateItem(container, position);
tagMap.put(position, frag.getTag());
return frag;
}
/**
* Return the Fragment associated with a specified position.
*
* #param position
*/
#Override
public Fragment getItem(int position) {
Fragment frag = null;
...
return frag;
}
/**
* Return the number of views available.
*/
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
String title = null;
...
return title;
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!
public String getFragmentTag(int position) {
return tagMap.get(position);
}
} // end of class TabAdapter
Then access within my activity (event methods) as:
String fragTag = tabAdapter.getFragmentTag(tabPosition);
Fragment frag = getSupportFragmentManager().findFragmentByTag(fragTag);
Of course this means you have to keep a reference of the adapter in your containing activity.
From here my fragments will have simple callbacks and explicit methods to update whatever views I need to update.

give initial data to fragments (with page adapter)

I have a problem,I want to send one argument extraData from my activityVenteActivity to one of his fragmentPageAdjuFragment at the creation of the activity.
I have 3 fragments on this activity for slide between them, for the moment I work only on PageAdjuFragment.
I see on stackoverflow how to use newinstantiate() for passing a bundle in argument for a new instance of PageAdjuFragment but that don't work for me :(.
You can see here my activity:
public class VenteActivity extends FragmentActivity {
private PagerAdapter mPagerAdapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.viewpager2);
creationPage();
//Recovery
Intent sender=getIntent();
String extraData=sender.getExtras().getString("message");
Log.v("nivyolo",extraData);//this is the argument which i would send
//Sending
PageAdjuFragment.newInstance(extraData); // the problem start here
}
public void creationPage() {
// Creation of the list
List<Fragment> fragments = new Vector<Fragment>();
// Add Fragments in a list
fragments.add(Fragment.instantiate(this,PageOffreFragment.class.getName()));
fragments.add(Fragment.instantiate(this,PageAdjuFragment.class.getName()));
fragments.add(Fragment.instantiate(this,PageNewPartFragment.class.getName()));
// Creation of theadapter
this.mPagerAdapter = new MyPagerAdapter(super.getSupportFragmentManager(), fragments);
ViewPager pager = (ViewPager) super.findViewById(R.id.viewpager2);
// Affectation on the ViewPager
pager.setAdapter(this.mPagerAdapter);
}
}
My fragment that I want to pass an argument to the creation
public class PageAdjuFragment extends Fragment {
public static PageAdjuFragment newInstance(String vente) {
PageAdjuFragment myFragment = new PageAdjuFragment();
Bundle args = new Bundle();
args.putString("vente", vente);
myFragment.setArguments(args);
return myFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
final View v=inflater.inflate(R.layout.page_adju_layout, container, false);
final Button b=(Button)v.findViewById(R.id.btconf);
final RadioGroup radiopmt = (RadioGroup) v.findViewById(R.id.radiopmt);
final RadioButton rb1 = (RadioButton)v.findViewById(R.id.rb1);
final RadioButton rb2 = (RadioButton)v.findViewById(R.id.rb2);
final AutoCompleteTextView tv1 = (AutoCompleteTextView)v.findViewById(R.id.actv1);
final AutoCompleteTextView tv2 = (AutoCompleteTextView)v.findViewById(R.id.actv2);
final EditText tv3 = (EditText)v.findViewById(R.id.edt);
////START PROBLEM////////
String vente;
// Recovery of the parameter
Log.v("adju","before recup");
Bundle arg = getArguments(); // the problem
Log.v("adju","after recup");
if (arg == null) {// all the time arg is null
Log.v("args","arguments is null ");
vente = "yolo";
} else {
Log.v("args2","arguments not null ");
vente= arg.getString("vente");
Log.v("nivyolobonnepage",vente);
}
tv3.setText(vente); //just a test
////END PROBLEM////////
//Data adaptation on TextAuto
List<String> OBJET = null;
List<String> PARTI = null;
try {
OBJET = InitObjet();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
PARTI = InitPart();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_dropdown_item_1line, OBJET);
tv1.setAdapter(adapter);
ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_dropdown_item_1line, PARTI);
tv2.setAdapter(adapter2);
Log.v("papaouté","ici"); //Listerner Boutton Confirmer
b.setOnClickListener(new OnClickListener() {...});
//Listener on the widget value's changes
tv1.addTextChangedListener(new TextWatcher() {...});
tv2.addTextChangedListener(new TextWatcher() {...});
tv3.addTextChangedListener(new TextWatcher() {...});
radiopmt.setOnCheckedChangeListener(new OnCheckedChangeListener() {...});
return v;
}
//Create the List of object
public List<String> InitObjet() throws IOException{...}
//Create the List of participant
public List<String> InitPart() throws IOException {...}
//Write in the CSV FILE "achat"
public void ecrire() throws IOException{...}
}
And finally the Page Adapter
public class MyPagerAdapter extends FragmentPagerAdapter {
private final List<Fragment> fragments;
//On fournit à l'adapter la liste des fragments à afficher
public MyPagerAdapter(FragmentManager fm, List fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int pos) {
return this.fragments.get(pos);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
and the wiewpager2.xml
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/viewpager2">
</android.support.v4.view.ViewPager>
the logCat
05-14 10:13:51.919: V/nivyolo(10005): vente1
05-14 10:13:52.169: V/adju(10005): before recup
05-14 10:13:52.169: V/adju(10005): after recup
05-14 10:13:52.169: V/args(10005): arguments is null
05-14 10:13:52.209: V/papaouté(10005): ici
The argument arg is always null
PageAdjuFragment.newInstance(extraData); // the problem start here
Yes there is your problem, because you're instantiating a Fragment and are not using it.
public class VenteActivity extends FragmentActivity {
private PagerAdapter mPagerAdapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setContentView(R.layout.viewpager2);
creationPage();
}
public void creationPage() {
// Creation of the list
List<Fragment> fragments = new Vector<Fragment>();
// Add Fragments in a list
fragments.add(Fragment.instantiate(this,PageOffreFragment.class.getName()));
//Recovery
Intent sender=getIntent();
String extraData=sender.getExtras().getString("message");
Log.v("nivyolo",extraData);//this is the argument which i would send
//Sending
Fragment frag = PageAdjuFragment.newInstance(extraData); // no problem anymore
fragments.add(frag);
fragments.add(Fragment.instantiate(this,PageNewPartFragment.class.getName()));
// Creation of theadapter
this.mPagerAdapter = new MyPagerAdapter(super.getSupportFragmentManager(), fragments);
ViewPager pager = (ViewPager) super.findViewById(R.id.viewpager2);
// Affectation on the ViewPager
pager.setAdapter(this.mPagerAdapter);
}
}
That's it. :-)
And why are you using Fragment.instantiate()? It's the same as using new Fragment(), but adds performance loss by using Java Reflection (approx. 2 times longer than using plain constructor). Better use the empty constructor or Fragment.newInstance(), if you defined that static method.

ListFragments Wrong Data Weird Pager

I hope someone can assist please. I have a Fragment hosting multiple list fragments using support library. The list fragments are supposed to display data that i retrieve form an async task in the parent fragment. I have been trying to figure out exactly how the data is being loaded because it is not loading correctly.
Each time the list display fragment is launched it preforms an async task to get and parse Json into an ArrayList <ArrayList <HashMap <String, String> > >
Each List fragment queries the parent fragment for data at its position in the ArrayList.
eg. For the 3rd page in it should retrieve arrList[2] which contains an `ArrayList <HashMap <String, String> > to display as a list.
The pager is acting weird. Maybe i am not understanding the lifecycle of the fragments or how the pager uses them. I have 7 Fragments. If i start on frag3 the pager will show fragment 3 with no data on it. It also loads fragment 2 and 4 with no data. If i go left to frag 1 it will display fragment 1 correctly and load fragment 0. I can properly switch to frag 0 but if i switch to frag 2 it loads data from frag 0 and loads frag 0's data into all of the rest of the views. If i go back and forth enough it will replace all data in every fragment with data from frag 0. I believe that it does not load data immediately because it does not have the data when the viewpager launches. I have not made it wait for the async task yet.
I thought that each fragment gets its view redrawn each time it is taken far enough from view. So i put Update in the onCreateView() of the fragment. I feel like this is a small thing that i have just misplaced or i am overlooking it. I tried to implement FragmentStatePagerAdapter but i do not think that i did it right.
Any Help is much Appreciated And i am very open to discussion if i am just doing things horribly wrong. I usually do. It never fails. Create something to find out i need to rewrite everything.
public class ListFragmentDisplay extends SherlockFragment {
public static final String TAG = "listFragmentDisplay";
Calendar calendar = Calendar.getInstance();
private int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
// listbyday is a list of hash maps each list of hash maps represents a day
// of the week with items for that Object
private ArrayList<ArrayList<HashMap<String, String>>> listByDay = null;
private String objectName = null;
private ViewPager pager;
private FragAdapter adapter;
public ArrayList<HashMap<String, String>> getList(int day) {
return listByDay.get(day);
}
private void getObjectName() {
barName = ((MainFragActivity) getActivity()).getobjectSelected();
}
public static ListFragmentDisplay newInstance() {
return new ListFragmentDisplay();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the ListView layout file.
initArrList();
getObjectName();
fillList();
return inflater.inflate(R.layout.list_view, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
pager = (ViewPager) view.findViewById(R.id.viewPager);
adapter =new FragAdapter(getChildFragmentManager());
if (pager.getAdapter() == null)
pager.setAdapter(adapter);
reload();
pager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageScrollStateChanged(int arg0) {}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {reload();}
#Override
public void onPageSelected(int arg0) {
}
});
pager.setCurrentItem(dayOfWeek-1);
}
private void initArrList() {
if (listByDay == null) {
listByDay = new ArrayList<ArrayList<HashMap<String, String>>>();
} else {
listByDay.clear();
}
for (int i = 0; i < 7; i++) {
ArrayList<HashMap<String, String>> hm = new ArrayList<HashMap<String, String>>();
listByDay.add(hm);
}
}
synchronized private void fillList() {
LoadWebTask lWT = new LoadWebTask();
executeAsyncTask(lWT, getSherlockActivity().getApplicationContext());
}
FragmentPager
public class FragAdapter extends FragmentPagerAdapter {
private static final String[] CONTENT = new String[] { "frag0", "frag1",
"frag2", "frag3", "frag4", "frag5", "frag6" };
public FragAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int arg0) {
return MyListFragment.newInstance(arg0);
}
#Override
public int getCount() {
return CONTENT.length;
}
#Override
public CharSequence getPageTitle(int position) {
return CONTENT[position % CONTENT.length];
}
}
ListFragment
public class MyListFragment extends SherlockListFragment {
public static final String NAME_TAG = "name";
public static final String DESCRIPTION_TAG = "description";
private static int dow;
public static final String TAG = "listFragment";
// Keys used in Hashmap that will be mapped to the rows
String[] dFrom = { NAME_TAG, DESCRIPTION_TAG };
private ArrayList<HashMap<String, String>> list;
int[] dTo = { R.id.name, R.id.description };
public void upDateList() {
//**************************Not really sure if this is how things are supposed
//** to be done. For my small data- set i feel like it will work but i would
//** be interested in knowing how else this might be done.
ListFragmentDisplay lFD = (ListFragmentDisplay) this
.getParentFragment();
dList = lFD.getList(dow);
}
public static MyListFragment newInstance(int pos) {
MyListFragment frag = new MyListFragment();
dow = pos;
return (frag);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
upDateList();
View results = inflater.inflate(R.layout.list_fragment, container,
false);
SimpleAdapter adapter = new SimpleAdapter(getParentFragment()
.getActivity(), list, R.layout.listrow, dFrom, dTo);
setListAdapter(adapter);
return results;
}
}
Edit. Solved Code: In List Fragment
The Initial Question has been solved. I am only in the process of implementing the onPostExecute callback to the ListFragmentDisplay. Much Thanks to Luksprog for solving my very noobish mistake. I made dow static without knowing its affect. I think it was actually something that Eclipse offered to solve a conflict. I should have read it closer.
public class MyListFragment extends SherlockListFragment {
public static final String NAME_TAG = "name";
public static final String DESCRIPTION_TAG = "description";
public static final String TAG = "listFragment";
// Keys used in Hashmap that will be mapped to the rows
String[] dFrom = { NAME_TAG, DESCRIPTION_TAG };
private ArrayList<HashMap<String, String>> list;
int[] dTo = { R.id.name, R.id.description };
SimpleAdapter adapter = null; **NEW**
public void upDateList() {
ListFragmentDisplay lFD = (ListFragmentDisplay) this
.getParentFragment();
dList = lFD.getList(getArguments().getInt(TAG)); **NEW**
if(adapter != null) **NEW**
adapter.notifyDataSetChanged(); **NEW**
}
public static MyListFragment newInstance(int pos) {
MyListFragment frag = new MyListFragment();
Bundle args = new Bundle(); **NEW**
args.putInt(TAG, pos); **NEW**
frag.setArguments(args); **NEW**
return (frag);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
upDateList();
View results = inflater.inflate(R.layout.list_fragment, container,
false);
adapter = new SimpleAdapter(getParentFragment()
.getActivity(), list, R.layout.listrow, dFrom, dTo);
setListAdapter(adapter);
return results;
}
}
Is there any reason why you made the dow variable from MyListFragment as static? With the static keyword your fragments from the ViewPager will share their position so you'll call the lFD.getList(dow); method with the wrong position most of the cases. Make dow a private instance field: private int dow;
About the rest of the code, it looks ok, see if the change above solves the problem. To update your data in the inner fragments you could follow this scenario:
start with an empty list of data in ListFragmentDisplay and start the task
initially, your inner ListFragmnents will see that the data list is empty so you'll initialize them with an empty list(the getList(int day) method should just return an empty list if there is no data in the listByDay field)
your task now finishes. Suppose you have a callback from the onPostExecute method of the AsyncTask. In that callback which the ListFragmentDisplay will implement you'll update every Fragment from the ViewPager which is either currently visible to the user or it's in the FragmentPagerAdapter alive(so each Fragment which is not null and its getView() method doesn't return null from the ViewPager will be updated). The other Fragments will self update because the onCreateView method will need to be called for them and you have the updateList call in there.
For the point above keep in mind that calling the updateList method will not update a visible Fragment because in that method you just update the list of the Fragment you don't call notifyDataSetChanged on the adapter to let it know that the data has changed.

Categories

Resources