How i use another Layout in ViewPager within a Fragment? - android

public class FormContentViewFragment extends Fragment implements View.OnClickListener {
private View view;
private View textView;
private TextView headerView;
private TextView fieldInstructionView;
private ImageButton backButton;
private ImageButton forwardButton;
private ProgressBar progressBar;
private ViewPager viewPager;
private int number;
private String value;
private String fieldinstruction;
private List<String> headerList = new ArrayList<String>();
private List<String> fieldInstructionList = new ArrayList<String>();
private LayoutInflater inflater;
private FormContentViewAdapter adapter;
public FormContentViewFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_form_content_view, container, false);
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
backButton = (ImageButton) view.findViewById(R.id.back_button);
forwardButton = (ImageButton) view.findViewById(R.id.forward_button);
progressBar = (ProgressBar) view.findViewById(R.id.progress_bar);
adapter = new FormContentViewAdapter();
Log.e("onActivityCreated()......","..........before set adapter........");
viewPager = (ViewPager) view.findViewById(R.id.view_pager);
viewPager.setAdapter(adapter);
Log.e("onActivityCreated()......","..........after set adapter........");
getViewContent();
}
public void getViewContent() {
MainActivity.showLoader(getActivity());
final StringRequest stringRequest = new StringRequest(Request.Method.GET, "JSON URL", new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.e("Response", ".............." + response);
try {
JSONObject jsonObject = new JSONObject(response);
boolean status = jsonObject.getBoolean("status");
if (status == true) {
JSONArray list = jsonObject.getJSONArray("list");
for (int i = 0; i < list.length(); i++) {
JSONObject currentData = list.getJSONObject(i);
number = currentData.getInt("number");
Log.e("number", "....." + number);
value = currentData.getString("value");
Log.e("value", "....." + value);
fieldinstruction = currentData.getString("fieldinstruction");
Log.e("fieldInstruction", "......" + fieldinstruction);
headerList.add(value);
Log.e("headerList...", "......" + headerList);
fieldInstructionList.add(fieldinstruction);
Log.e("instructioList", "....." + fieldInstructionList);
Toast.makeText(getContext(), "Dispaly data", Toast.LENGTH_SHORT).show();
}
// headerView.setText(headerList.get(1));
// fieldInstructionView.setText(fieldInstructionList.toString());
}
MainActivity.hideLoader();
} catch (JSONException e) {
e.printStackTrace();
MainActivity.hideLoader();
}
Log.e("number out.....", "....." + number);
MainActivity.hideLoader();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
String errorResponse = String.valueOf(error.networkResponse.data);
Log.e("ErrorResponse", "........" + errorResponse);
MainActivity.hideLoader();
}
}) {
};
ApplicationController.getInstance().addToRequestQueue(stringRequest);
}
#Override
public void onClick(View view) {
}
class FormContentViewAdapter extends PagerAdapter {
public FormContentViewAdapter(){
Log.e("FormContentViewAdapter","..............inside....");
Log.e("headerList1...", "......" + headerList.toString());
Log.e("instructioList1...", "....." + fieldInstructionList.toString());
Log.e("FormContentViewAdapter","..............end of it....");
}
#Override
public int getCount() {
Log.e("headerList1...", "......" + headerList.toString());
Log.e("instructioList1...", "....." + fieldInstructionList.toString());
Log.e("value getCount().......","........"+number);
return number;
}
#Override
public boolean isViewFromObject(View view, Object object) {
Log.e("isViewFromObject().....","inside.........");
return false;
}
#Override
public View instantiateItem(ViewGroup container, int position) {
Log.e("instantiateItem()......","inside.........");
textView = inflater.inflate(R.layout.view_pager_content, container, false);
headerView = (TextView) textView.findViewById(R.id.header_text_view);
fieldInstructionView = (TextView) textView.findViewById(R.id.instruction_text_view);
headerView.setText(headerList.get(position));
Log.e("headerList2.....","............."+headerList.toString());
fieldInstructionView.setText(fieldInstructionList.toString());
Log.e("fieldInstructionList2........",".........."+fieldInstructionList.get(position));
container.addView(textView);
Log.e("instantiateItem()......","end of it.........");
return textView;
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
}
}
Error:
java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 0, found: 2 Pager id: com.formfilling:id/view_pager Pager class: class android.support.v4.view.ViewPager Problematic adapter: class com.formfilling.FormContentViewFragment$FormContentViewAdapter
at android.support.v4.view.ViewPager.populate(ViewPager.java:1171)
at android.support.v4.view.ViewPager.populate(ViewPager.java:1120)
at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1646)
I have single Fragment, within that ViewPager is there I want to set the different layout to that ViewPager So I also use an adapter to set the layout in ViewPager but it throws an error IllegalStateException. I already doing all things for that but it is not working.Give your suggestions

Actually, you are trying to reference Activity's number variable directly inside pagerAdapter's getCount() method. While the ViewPager is doing its thing, it references the adapter again and again. So it checks that getCount() .But your Background thread changes the number variable value to some new value ,which causes a mismatch in the previous value which was 0 in the pagerAdapter. Hence IllegalStateException will be thrown
Note:getCount() may be called several times by the ViewPager. It must remain constant, for the life of the PagerAdapter .
Recommended option is to keep the getCount value to some constant value if you know how many pages to be shown, but if it changes Dynamically, then there is a way, whenever your number changes, you have to set the adapter again to the viewPager, notifyDataSetChanged will not work for this situation.
you have to do something like this inside your onResponse method as shown below
number = currentData.getInt("number");
viewPager.setAdapter(adapter);
this will again clear the count and take a new count which will be your new value.

Related

Webservices with Retained Fragments

I have a Fragment that is used to retrieve some data from my CMS with the help of the Volley lib. I am using RecyclerViews to do that. It works. However when I am rotating the screen,the webservice is run again. How can I stop that? I tried to use **setRetainInstance(true); but at no vail. From what I have read,this method bypasses the onDestroy() fragment's method,and hence the onCreate() fragment's method is not called when you rotate the screen. If I am wrong with that please correct me. Here is my code.
FeaturesActivity
public class FeaturesActivity extends AppCompatActivity {
private static final String FEATURES_FRAGMENT = "Features_fragment";
FeaturesFragment ff;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_features);
FragmentManager fragmentManager = getSupportFragmentManager();
ff = (FeaturesFragment) fragmentManager.findFragmentByTag(FEATURES_FRAGMENT);
if(ff == null) {
ff = new FeaturesFragment();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(android.R.id.content, ff);
fragmentTransaction.commit();
}
}
}
And the actual fragment itself.
public class FeaturesFragment extends Fragment {
public static final String TAG = "ManuApp";
private static final String IMAGE_URL = "http://xxx/xxx/features_images/" ;
private List<FeaturesObject> listItemsList;
private RecyclerView mRecyclerView;
private FeaturesAdapter adapter;
public FeaturesFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
Log.v("retained","oncreate called");
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_features, container, false);
// Inflate the layout for this fragment
listItemsList = new ArrayList<>();
mRecyclerView = (RecyclerView)v.findViewById(R.id.features_recycler_view);
//mRecyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getActivity()).color(Color.BLACK).build());
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(linearLayoutManager);
return v;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
updateFeaturesList();
}
public void updateFeaturesList() {
//declare the adapter and attach it to the recyclerview
adapter = new FeaturesAdapter(getActivity(), listItemsList);
mRecyclerView.setAdapter(adapter);
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(getActivity());
// Request a string response from the provided URL.
JsonArrayRequest jsObjRequest = new JsonArrayRequest(Request.Method.GET, Config.URL_FEATURES, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
//hidePD();
// Parse json data.
// Declare the json objects that we need and then for loop through the children array.
// Do the json parse in a try catch block to catch the exceptions
try {
for (int i = 0; i < response.length(); i++) {
JSONObject post = response.getJSONObject(i);
FeaturesObject item = new FeaturesObject();
item.setTitle(post.getString("title"));
item.setImage(IMAGE_URL + post.getString("features_image"));
item.setArticle(post.getString("article"));
listItemsList.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
// Update list by notifying the adapter of changes
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
//hidePD();
}
});
queue.add(jsObjRequest);
}
}
I logged out a message inside the onCreate(...),but it is called even if I rotate the screen. How can I fix that?
Thanks.
I fixed it using the following code inside the manifest.xml file
android:configChanges="screenSize|orientation"
Google though states that we should use that as a resourse.

I get NullPointerException when my app hasn't been open for a while

I have a simple weather app that consists of a view pager with 3 fragments (Current, Hourly and Daily weather forecast). When I launch my app for the very first time it works fine as well as I close and open it. However, I have noticed that when my app has been in the background processes for a while and then I open it, it crashes with this exception:
java.lang.NullPointerException: Attempt to read from field 'koemdzhiev.com.stormy.weather.Forecast koemdzhiev.com.stormy.ui.MainActivity.mForecast' on a null object reference
at koemdzhiev.com.stormy.ui.Current_forecast_fragment.updateDisplay(Current_forecast_fragment.java:120)
at koemdzhiev.com.stormy.ui.MainActivity$3$3.run(MainActivity.java:234)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5294)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
I suspect that this exception has something to do with the fact that I am not saving data using the saveInstance method.
This is my current fragment code:
public class Current_forecast_fragment extends Fragment {
private static final String TAG = "MainActivity";
private MainActivity mActivity;
TextView mTimeLabel;
TextView mTemperatureLabel;
TextView mHumidityValue;
TextView mPrecipValue;
TextView mSummaryLabel;
TextView mLocationLabel;
TextView mWindSpeedValue;
TextView mFeelsLike;
ImageView mIconImageView;
ImageView mDegreeImageView;
public SwipeRefreshLayout mSwipeRefreshLayout;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = ((MainActivity) getActivity());
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.current_forefast_fragment, container, false);
mTimeLabel = (TextView)v.findViewById(R.id.timeLabel);
mTemperatureLabel = (TextView)v.findViewById(R.id.temperatureLabel);
mHumidityValue = (TextView)v.findViewById(R.id.humidityValue);
mPrecipValue = (TextView)v.findViewById(R.id.precipValue);
mSummaryLabel = (TextView)v.findViewById(R.id.summaryLabel);
mLocationLabel = (TextView)v.findViewById(R.id.locationLabel);
mWindSpeedValue = (TextView)v.findViewById(R.id.windSpeedValue);
mFeelsLike = (TextView)v.findViewById(R.id.feels_like_label);
mIconImageView = (ImageView)v.findViewById(R.id.iconImageView);
mDegreeImageView = (ImageView)v.findViewById(R.id.degreeImageView);
mSwipeRefreshLayout = (SwipeRefreshLayout)v.findViewById(R.id.current_swipe_refresh_layout);
mSwipeRefreshLayout.setColorSchemeResources(R.color.orange, R.color.blue, R.color.green);
mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
Log.d("TAG", "Swiping in current!");
//if there is internet and if the mSwipeRefreshLayout in the Hourly and daily fragments are not already running...
if (mActivity.isNetworkAvailable()) {
if (!mActivity.mHourly_forecast_fragment.mSwipeRefreshLayout.isRefreshing() && !mActivity.mDaily_forecast_fragment.mSwipeRefreshLayout.isRefreshing()) {
if (mActivity.isLocationServicesEnabled()) {
if (mActivity.latitude != 0.0 && mActivity.longitude != 0.0) {
mActivity.getForecast(mActivity.latitude, mActivity.longitude);
} else {
mActivity.getLocation();
}
}else{
mActivity.alertForNoLocationEnabled();
}
}else{
mSwipeRefreshLayout.setRefreshing(false);
Toast.makeText(mActivity, "currently refreshing...", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(mActivity, "No Internet Connection!", Toast.LENGTH_LONG).show();
mSwipeRefreshLayout.setRefreshing(false);
}
}
});
//Start the swipe refresh layout on start up is internet available
if(mActivity.isNetworkAvailable())
mSwipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
Log.d("TAG","running swiping...");
}
});
return v;
}
public void updateDisplay() {
if(mActivity.mForecast != null) {
Current current = mActivity.mForecast.getCurrent();
//setting the current weather details to the ui
mTemperatureLabel.setText(current.getTemperature() + "");
mTimeLabel.setText("At " + current.getFormattedTime() + " it is");
mHumidityValue.setText(current.getHumidity() + "%");
mPrecipValue.setText(current.getPrecipChange() + "%");
mSummaryLabel.setText(current.getSummery());
mWindSpeedValue.setText(current.getWindSpeed() + "");
mFeelsLike.setText("Feels like: " + current.getFeelsLike());
mLocationLabel.setText(mActivity.locationName);
Drawable drawable = ContextCompat.getDrawable(mActivity, current.getIconId());
mIconImageView.setImageDrawable(drawable);
}else{
Toast.makeText(getActivity(),"Could not update data at this time! Please, try again.",Toast.LENGTH_LONG).show();
}
}
}
Fragment page adapter code:
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private Current_forecast_fragment mCurrent_forecast_fragment;
private Hourly_forecast_fragment mHourly_forecast_fragment;
private Daily_forecast_fragment mDaily_forecast_fragment;
CharSequence Titles[]; // This will Store the Titles of the Tabs which are Going to be passed when ViewPagerAdapter is created
int NumbOfTabs; // Store the number of tabs, this will also be passed when the ViewPagerAdapter is created
// Build a Constructor and assign the passed Values to appropriate values in the class
public ViewPagerAdapter(FragmentManager fm,CharSequence mTitles[], int mNumbOfTabsumb,Current_forecast_fragment current_fragment,
Hourly_forecast_fragment hourly_fragment,
Daily_forecast_fragment daily_fragment) {
super(fm);
this.mCurrent_forecast_fragment = current_fragment;
this.mHourly_forecast_fragment = hourly_fragment;
this.mDaily_forecast_fragment = daily_fragment;
this.Titles = mTitles;
this.NumbOfTabs = mNumbOfTabsumb;
}
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
if(position == 0) // if the position is 0 we are returning the First tab
{
return this.mCurrent_forecast_fragment;
}
else if (position == 1) // As we are having 2 tabs if the position is now 0 it must be 1 so we are returning second tab
{
return this.mHourly_forecast_fragment;
}else {
return this.mDaily_forecast_fragment;
}
}
// This method return the titles for the Tabs in the Tab Strip
#Override
public CharSequence getPageTitle(int position) {
return Titles[position];
}
// This method return the Number of tabs for the tabs Strip
#Override
public int getCount() {
return NumbOfTabs;
}
}
My main activity code:
public class MainActivity extends AppCompatActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.mCurrent_forecast_fragment = new Current_forecast_fragment();
this.mHourly_forecast_fragment = new Hourly_forecast_fragment();
this.mDaily_forecast_fragment = new Daily_forecast_fragment();
// Creating The ViewPagerAdapter and Passing Fragment Manager, Titles fot the Tabs and Number Of Tabs.
adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles, Numboftabs, mCurrent_forecast_fragment,
mHourly_forecast_fragment, mDaily_forecast_fragment);
// Assigning ViewPager View and setting the adapter
pager = (ViewPager) findViewById(R.id.pager);
pager.setOffscreenPageLimit(3);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) findViewById(R.id.tabs);
tabs.setDistributeEvenly(true); // To make the Tabs Fixed set this true, This makes the tabs Space Evenly in Available width
// Setting Custom Color for the Scroll bar indicator of the Tab View
tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return ContextCompat.getColor(MainActivity.this, R.color.tabsScrollColor);
}
});
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
}
I have this method in MainActivity which updates the data in the fragments:
public void getForecast(double latitude, double longitude) {
//scedule no response from the server task...
mScheduledFuture = exec.schedule(mNotAbleToGetWeatherDataTask,12, TimeUnit.SECONDS);
Log.d(TAG, "getForecast initiated...");
String API_KEY = "3ed3a1906736c6f6c467606bd1f91e2c";
String forecast = "https://api.forecast.io/forecast/" + API_KEY + "/" + latitude + "," + longitude + "?units=si";
if (isNetworkAvailable()) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(forecast)
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
toggleSwipeRefreshLayoutsOff();
}
});
#Override
public void onResponse(Response response) throws IOException {
runOnUiThread(new Runnable() {
#Override
public void run() {
toggleSwipeRefreshLayoutsOff();
}
});
try {
String jsonData = response.body().string();
if (response.isSuccessful()) {
mForecast = parseForecastDetails(jsonData);
runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d(TAG, "isSuccessful - run on UNI threth (update display)...");
//THIS LINE BELLOW CAUSES THE NPE...
mCurrent_forecast_fragment.updateDisplay();
mHourly_forecast_fragment.setUpHourlyFragment();
mDaily_forecast_fragment.setUpDailyFragment();
toggleSwipeRefreshLayoutsOff();
//set the isFirstTime to true so that the next refresh wont get location
isFirstTimeLaunchingTheApp = false;
}
});
} else {
alertUserAboutError();
}
} catch (IOException | JSONException e) {
Log.e(TAG, "Exception caught:", e);
}
}
Is because mActivity is null.
Add this line in onResume() method
mActivity = ((MainActivity) getActivity());
Like this
#Override
public void onResume() {
super.onResume();
mActivity = ((MainActivity) getActivity());
}

How to update fragment's data used in ViewPager? View is not showing the updated data

I know the same question has been asked so many times but I am not able to solve my issue.
I have created an Activity which has a ViewPager which should have 4 Pages.
I am using the same Fragment for all pages. The Fragment has a GridView which should be updated whenever I swipe to the other page.
Following are the classes & XML layouts I have used to create it.
Activity layout activity_discover.xml
<android.support.v4.view.ViewPager
android:id="#+id/activity_discover_view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dip" >
<android.support.v4.view.PagerTabStrip
android:id="#+id/activity_discover_pager_tab_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:textColor="#color/black"
android:textSize="#dimen/header_text" />
</android.support.v4.view.ViewPager>
</RelativeLayout>
Activity DiscoverActivity.java
public class DiscoverActivity extends FragmentActivity implements OnClickListener, OnPageChangeListener
{
private final static String TAG = "DiscoverActivity";
private UtilDialog utilDialog;
MPagerAdapter adapterViewPager;
PagerTabStrip pagerTabStrip;
ViewPager viewPager;
public ArrayList<String> listCategory;
LMProgressDialog progressDialog;
private RelativeLayout relativeCountry;
private RelativeLayout relativeCity;
private TextView tvCountry;
private TextView tvCity;
private String selectedCategory;
private int selectedCityID = 0;
private int selectedCategoryID = 0;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_discover);
initParameters();
initView();
}
void initParameters()
{
progressDialog = new LMProgressDialog(this);
utilDialog = new UtilDialog(this);
preferences = PreferenceManager.getDefaultSharedPreferences(this);
editor = preferences.edit();
editor.commit();
selectedCategory = getResources().getString(R.string.adventure);
listCategory = new ArrayList<String>();
listCategory.add(getResources().getString(R.string.adventure));
listCategory.add(getResources().getString(R.string.night_life));
listCategory.add(getResources().getString(R.string.life_styles));
listCategory.add(getResources().getString(R.string.events));
}
void initView()
{
viewPager = (ViewPager) findViewById(R.id.activity_discover_view_pager);
viewPager.setOnPageChangeListener(this);
adapterViewPager = new MPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(adapterViewPager);
pagerTabStrip = (PagerTabStrip) findViewById(R.id.activity_discover_pager_tab_strip);
pagerTabStrip.setTabIndicatorColor(getResources().getColor(R.color.white));
}
#Override
protected void onDestroy()
{
super.onDestroy();
}
public class MPagerAdapter extends FragmentPagerAdapter
{
private Map<Integer, String> mFragmentTags;
private FragmentManager mFragmentManager;
public MPagerAdapter(FragmentManager fm)
{
super(fm);
mFragmentManager = fm;
mFragmentTags = new HashMap<Integer, String>();
}
#Override
public int getCount()
{
return 4;
}
#Override
public Fragment getItem(int position)
{
Fragment fragment = Fragment.instantiate(DiscoverActivity.this,
FragmentMediaContent.class.getName(), null);
return fragment;
}
#Override
public Object instantiateItem(ViewGroup container, int position)
{
Object obj = super.instantiateItem(container, position);
if (obj instanceof Fragment)
{
// record the fragment tag here.
Fragment f = (Fragment) obj;
String tag = f.getTag();
mFragmentTags.put(position, tag);
}
return obj;
}
public Fragment getFragment(int position)
{
String tag = mFragmentTags.get(position);
if (tag == null)
return null;
return mFragmentManager.findFragmentByTag(tag);
}
#Override
public CharSequence getPageTitle(int position)
{
return listCategory.get(position).toString().toUpperCase();
}
}
#Override
public void onPageScrollStateChanged(int arg0)
{
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
}
#Override
public void onPageSelected(int position)
{
selectedCategoryID = position;
selectedCategory = listCategory.get(position);
try
{
JSONObject jsonObject = new JSONObject();
jsonObject.put(Constants.CITY_ID, selectedCityID);
jsonObject.put(Constants.CATEGORY, selectedCategory);
makeJsonObjectRequest(Request.Method.POST, jsonObject, API.URL_LOAD_MEDIA);
} catch (JSONException e)
{
e.printStackTrace();
}
}
void prepareMediaList(JSONArray arrayMedia)
{
int noOfMedia = arrayMedia.length();
ArrayList<MediaType> listMedia = new ArrayList<MediaType>();
for (int i = 0; i < noOfMedia; i++)
{
try
{
JSONObject objectMedia = arrayMedia.getJSONObject(i);
int id = objectMedia.getInt(Constants.ID);
String category = objectMedia.getString(Constants.CATEGORY);
String mediaType = objectMedia.getString(Constants.MEDIA_TYPE);
int cityID = objectMedia.getInt(Constants.CITIES_ID);
String path = objectMedia.getString(Constants.PATH);
String thumbnailPath = objectMedia.getString(Constants.THUMBNAIL_PATH);
String description = objectMedia.getString(Constants.DESCRIPTION);
int userID = objectMedia.getInt(Constants.USERS_ID);
listMedia.add(new MediaType(id, mediaType, path, category, userID, cityID, 0, description, thumbnailPath));
} catch (JSONException e)
{
e.printStackTrace();
}
}
FragmentMediaContent fragment = (FragmentMediaContent) adapterViewPager.getFragment(selectedCategoryID);
Log.i(TAG, "fragment: " + fragment);
fragment.updateData(listMedia, selectedCategory);
}
}
Fragment class FragmentMediaContent.java:
public class FragmentMediaContent extends Fragment
{
private final static String TAG = "FragmentMediaContent";
public static final String FRAGMENT_POSITION = null;
private GridView gridView;
private UtilDialog utilDialog;
private SharedPreferences preferences;
private Editor editor;
private ArrayList<MediaType> listMedia;
MediaAdapter mediaAdapter;
private int cityID;
private String category;
LMProgressDialog progressDialog;
TextView tvTest;
public static FragmentMediaContent newInstance(int num)
{
FragmentMediaContent f = new FragmentMediaContent();
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState)
{
return inflater.inflate(R.layout.fragment_media_content, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
initParameters();
initViews();
}
void initParameters()
{
getSize();
listMedia = new ArrayList<MediaType>();
utilDialog = new UtilDialog(getActivity());
progressDialog = new LMProgressDialog(getActivity());
preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
editor = preferences.edit();
mediaAdapter = new MediaAdapter(getActivity(), listMedia);
}
void initViews()
{
tvTest = (TextView) getActivity().findViewById(R.id.fragment_media_content_tv_test);
tvTest.setText(category+" no of media");
tvTest.setVisibility(View.GONE);
gridView = (GridView) getActivity().findViewById(R.id.fragment_media_content_grid_view);
gridView.setAdapter(mediaAdapter);
}
/**
* MediaAdapter : ArrayAdapter class which prepares view for list of
* MediaType.
*
*/
class MediaAdapter extends ArrayAdapter<MediaType>
{
MediaAdapter(Context context, ArrayList<MediaType> list)
{
super(context, R.layout.cell_media_view, R.id.cell_media_view_tv_test, list);
}
public View getView(int position, View convertView, ViewGroup parent)
{
View row = super.getView(position, convertView, parent);
MediaViewHolder holder = (MediaViewHolder) row.getTag();
if (holder == null)
{
holder = new MediaViewHolder(row);
row.setTag(holder);
}
final MediaType mediaType = getMedia(position, this);
String thumbnailPath = mediaType.getThumbnailPath();
String path = mediaType.getPath();
String type = mediaType.getMediaType();
// imageLoader.get(type.equals(Constants.TYPE_IMAGE) ? path :
// thumbnailPath, ImageLoader.getImageListener(holder.ivMedia,
// R.drawable.logo, R.drawable.ic_launcher));
holder.ivType.setVisibility(type.equals(Constants.TYPE_IMAGE) ? View.GONE : View.VISIBLE);
holder.ivMedia.setLayoutParams(new FrameLayout.LayoutParams(THUMBNAIL_SIZE, THUMBNAIL_SIZE));
Picasso.with(getActivity()).load(type.equals(Constants.TYPE_IMAGE) ? path : thumbnailPath).noFade().centerCrop().resize(THUMBNAIL_SIZE, THUMBNAIL_SIZE).placeholder(R.drawable.loading)
.error(R.drawable.no_image).into(holder.ivMedia);
return row;
}
}
public void updateData(ArrayList<MediaType> listMedia, String category)
{
Log.i(TAG, "Updating data for: " + category);
Log.i(TAG, "No of media items: " + listMedia.size());
// this.listMedia.clear();
// this.listMedia.addAll(listMedia);
// mediaAdapter.notifyDataSetChanged();
mediaAdapter = new MediaAdapter(getActivity(), listMedia);
gridView.setAdapter(mediaAdapter);
tvTest.setText(category + ", No of Media : " + listMedia.size());
}
int THUMBNAIL_SIZE = 200;
/**
* #param position
* #return MediaType object from specified position
*/
private MediaType getMedia(int position, MediaAdapter mediaAdapter)
{
return (MediaType) mediaAdapter.getItem(position);
}
}
Fragment fragment_media_content.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/blue"
android:gravity="center"
android:orientation="vertical" >
<TextView
android:id="#+id/fragment_media_content_tv_test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/white" />
<GridView
android:id="#+id/fragment_media_content_grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:horizontalSpacing="5dip"
android:numColumns="3"
android:verticalSpacing="5dip" />
</LinearLayout>
On page swipe (or it could be any other event) I hit an API which gives me some data that I have to update in the corresponding Fragment.
Whenever I get the data from server I call the prepareMediaList method which calls the updateData method of Fragment. I can see in logs that there is data in list but that data is not shown in the Fragment's GridView (not even in TextView).
I am really not getting what is wrong in this.
Now it has become very frustrating, looks so simple but still couldn't find any solution.
Edit
I just tried with one Fragment only & it is working properly. So there is something which has to do with multiples.
Edit 2
I couldn't find the solution for this so I had to switch to alternate way. I removed the Fragments from ViewPager instead I added static views to it. In my case I added four GridViews to ViewPager. This was simple & bit complex but most important thing is, it is working the way I wanted.
But still I am looking for the answer.
After checking your code more in details i see you do not require to re-initliaze your MediaAdapter inside updateData method.
You simply require to update your updateData as
listMedia.clear();
this.listMedia.addAll(listMedia);
mediaAdapter.notifyDatasetChanged();
This will reload your data in gridview. Change i suggested will refresh the data in your arraylist which is being used for rendering gridview and then you notify your mediaAdapter to reload the list.

How to manipulate view inside ListView items?

I have a ListView in which there several rows containing two buttons and a ProgressBar (Visibility:GONE) each.
My purpose is to display the ProgressBar upon click on the buttons and after completing a certain set of background operations remove that row entirely.
The problem here is that after removing the item from the ArrayList which the ListView is created upon and calling notifyDataSetChanged the row is removed successfully but the ProgressBar remains visible.
Shouldn't it be removed along with it's parent view?
Checkout the following record to see the problem in action.
Here is the source of my entire fragment:
public class FriendRequestFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static final String TAG = "FriendRequestFragment";
ArrayList<FriendRequest> friendRequests;
#InjectView(R.id.friendRequestList)
ListView mListView;
#InjectView(R.id.noRequestsText)
TextView noRequestsText;
#InjectView(R.id.swipe)
SwipeRefreshLayout swipeRefreshLayout;
// NotificationHandler nh;
/**
* The Adapter which will be used to populate the ListView/GridView with
* Views.
*/
private FriendRequestAdapter mAdapter;
private Context c;
private boolean isProcessing = false;
/**
* Mandatory empty constructor for the fragment manager to instantiate the
* fragment (e.g. upon screen orientation changes).
*/
public FriendRequestFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Util.trackFragment(this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_friendrequest_list, container, false);
ButterKnife.inject(this, view);
c = getActivity();
friendRequests = new ArrayList<>();
swipeRefreshLayout.setOnRefreshListener(this);
mAdapter = new FriendRequestAdapter(getActivity(), friendRequests);
mListView.setAdapter(mAdapter);
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
int topRowVerticalPosition =
(view == null || view.getChildCount() == 0) ?
0 : view.getChildAt(0).getTop();
swipeRefreshLayout.setEnabled(firstVisibleItem == 0 && topRowVerticalPosition >= 0);
Log.d(TAG, "SwipeRefresh: " + String.valueOf(firstVisibleItem == 0 && topRowVerticalPosition >= 0));
}
});
loadRequests();
return view;
}
private void loadRequests() {
// nh = new NotificationHandler(getActivity());
swipeRefreshLayout.setRefreshing(true);
Log.d(TAG, "loading requests init");
HashMap<String, Integer> params = new HashMap<>();
params.put("profile_id", Util.getCurrentProfileID(c));
final String uniqueID = Util.getCurrentProfileID(c) + String.valueOf(System.currentTimeMillis() / 1000 / 1200);
new ApiRequest(Util.URL_GET_FRIEND_REQUESTS, params, new AjaxCallback<String>() {
#Override
public void callback(String url, String result, AjaxStatus status) {
super.callback(url, result, status);
ApiResponse apiResponse = new ApiResponse(url, result, uniqueID);
Log.d(TAG, "Friend Requests Response: " + result);
if (apiResponse.isSuccessful()) {
JSONArray jsonArray = apiResponse.getDataJSONArray();
try {
for (int i = 0; i < jsonArray.length(); i++) {
friendRequests.add(new FriendRequest(jsonArray.getJSONObject(i)));
}
mAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
mListView.setVisibility(View.VISIBLE);
} else if (apiResponse.getErrorMessage().equals("request_not_found")) {
noRequestsText.setVisibility(View.VISIBLE);
}
swipeRefreshLayout.setRefreshing(true);
}
}).setUniqueID(uniqueID).execute();
}
#Override
public void onRefresh() {
loadRequests();
}
private void acceptRequest(final int position, final View rootView) {
if (isProcessing) {
CustomToast.makeToast(getActivity(), CustomToast.TYPE_ALERT, getString(R.string.please_wait), CustomToast.LENGTH_SHORT);
return;
}
rootView.findViewById(R.id.loading).setVisibility(View.VISIBLE);
rootView.findViewById(R.id.acceptBtn).setVisibility(View.GONE);
rootView.findViewById(R.id.denyBtn).setVisibility(View.GONE);
isProcessing = true;
Log.d("FriendRequest", "accepting:" + position);
FriendRequest request = friendRequests.get(position);
HashMap<String, Integer> params = new HashMap<>();
params.put("request_id", request.getRequestID());
params.put("profile_id", ProfilesSingleton.getInstance().getCurrentProfile().getProfileID());
new ApiRequest(Util.URL_ACCEPT_REQUEST, params, new AjaxCallback<String>() {
#Override
public void callback(String url, String object, AjaxStatus status) {
super.callback(url, object, status);
ApiResponse apiResponse = new ApiResponse(object);
if (apiResponse.isSuccessful()) {
friendRequests.remove(position);
CustomToast.makeToast(getActivity(), CustomToast.TYPE_DEFAULT,
getString(R.string.you_are_now_friends_with) + " " + friendRequests.get(position).getFullName(),
CustomToast.LENGTH_SHORT);
mAdapter.notifyDataSetChanged();
}else {
rootView.findViewById(R.id.loading).setVisibility(View.GONE);
rootView.findViewById(R.id.acceptBtn).setVisibility(View.VISIBLE);
rootView.findViewById(R.id.denyBtn).setVisibility(View.VISIBLE);
}
isProcessing = false;
}
}).execute();
}
private void denyRequest(final int position, final View rootView) {
if (isProcessing) {
CustomToast.makeToast(getActivity(), CustomToast.TYPE_ALERT, getString(R.string.please_wait), CustomToast.LENGTH_SHORT);
return;
}
rootView.findViewById(R.id.loading).setVisibility(View.VISIBLE);
rootView.findViewById(R.id.acceptBtn).setVisibility(View.GONE);
rootView.findViewById(R.id.denyBtn).setVisibility(View.GONE);
Log.d("FriendRequest", "denying:" + position);
FriendRequest request = friendRequests.get(position);
HashMap<String, Integer> params = new HashMap<>();
params.put("request_id", request.getRequestID());
params.put("profile_id", ProfilesSingleton.getInstance().getCurrentProfile().getProfileID());
new ApiRequest(Util.URL_DENY_REQUEST, params, new AjaxCallback<String>() {
#Override
public void callback(String url, String object, AjaxStatus status) {
super.callback(url, object, status);
ApiResponse apiResponse = new ApiResponse(object);
if (apiResponse.isSuccessful()) {
friendRequests.remove(position);
mAdapter.notifyDataSetChanged();
}else {
rootView.findViewById(R.id.loading).setVisibility(View.GONE);
rootView.findViewById(R.id.acceptBtn).setVisibility(View.VISIBLE);
rootView.findViewById(R.id.denyBtn).setVisibility(View.VISIBLE);
}
}
}).execute();
}
public class FriendRequestAdapter extends ArrayAdapter<FriendRequest> {
public FriendRequestAdapter(Context context, ArrayList<FriendRequest> objects) {
super(context, 0, objects);
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View rootView = convertView;
final ViewHolder holder;
final FriendRequest friendRequest = getItem(position);
if (rootView == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rootView = inflater.inflate(R.layout.friend_request_item, parent, false);
holder = new ViewHolder();
holder.profilePhoto = (RoundedImageView) rootView.findViewById(R.id.profilePhoto);
holder.fullName = (TextView) rootView.findViewById(R.id.fullName);
holder.acceptBtn = (ImageView) rootView.findViewById(R.id.acceptBtn);
holder.denyBtn = (ImageView) rootView.findViewById(R.id.denyBtn);
holder.loading = (ProgressBar) rootView.findViewById(R.id.loading);
rootView.setTag(holder);
} else {
holder = (ViewHolder) rootView.getTag();
}
holder.fullName.setText(friendRequest.getFullName());
if (friendRequest.getFullPhotoPath().equals("")) {
ImageUtil.replaceWithInitialsView(getContext(), holder.profilePhoto, friendRequest.getInitials());
} else {
Util.aQuery.id(holder.profilePhoto).image(friendRequest.getFullPhotoPath(), false, true, 50, R.drawable.avatar_profile, null, AQuery.FADE_IN);
}
final View finalRootView = rootView;
holder.acceptBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
acceptRequest(position, finalRootView);
}
});
holder.denyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
denyRequest(position, finalRootView);
}
});
return rootView;
}
public class ViewHolder {
RoundedImageView profilePhoto;
TextView fullName;
ImageView acceptBtn, denyBtn;
ProgressBar loading;
}
}
}
Add a field in your FriendRequest class that saves the current state of the progress bar. based on it set the visibility of the progress bar.
The same view row has been sent to another row. in your getView method you must always set the progress bar visibility based on its status.
Code Sample:
final View finalRootView = rootView;
if (friendRequest.acceptingRequestInProgress())
holder.loading.setVisibility(View.Visibile);
else
holder.loading.setVisibility(View.Gone);
holder.acceptBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
friendRequest.setAcceptingInProgress(true);
acceptRequest(position, finalRootView);
}
});
holder.denyBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
denyRequest(position, finalRootView);
}
});
Another place to modify:
if (apiResponse.isSuccessful()) {
friendRequest.setAcceptingInProgress(false);
friendRequests.remove(position);
mAdapter.notifyDataSetChanged();
}
Note: this is also handles the case when the user scrolls the list
view and the row view in progress is no longer visible. this will
hands the view to another row. But since we check the row state the
progress bar will be stopped. and when user scrolls back to the row
view in progress and hands it a reusable view the progress bar will be
visible again if accepting is still in progress.
Views are getting reused by the ListView and in the getView() method you are not cleaning up the reused view, that's why the progress bar will become visible for an item that shouldn't display it.
Similarly if an item would be removed some items with progress bars visible would loose their progress bar, handing them over to an item that didn't need it.
In getView(), after initializing the holder, you should check if progress bar is necessary.
Start with storing progress bar values at the beginning:
private ArrayList<Integer> progresses = new ArrayList<Integer>();
Update these values every time the list changes (when list changes in loadRequests and when value changes not sure where).
And in getView()
if (progresses.get(position) == 100) {
holder.loading.setVisibility(View.GONE);
} else {
holder.loading.setVisibility(View.VISIBLE);
holder.loading.setProgress(progresses.get(position));
}
The problem is due to visibility of progressbar is VISIBLE default so in getView() after you call notifyDataSetChanged(), the progressbar becomes visible to row position (i - 1).
holder.loading = (ProgressBar) rootView.findViewById(R.id.loading);
holder.loading.setVisibility(View.GONE);
Set progressbar visibility to GONE in getView() and this problem will not come

Android getActivity().setTitle() gets String field from wrong object in ArrayList

I wish to set the titlebar in this fragment's activity to the HelpItem's description field.
On line 10, I set the title of the activity with a String representing a HelpItem's description.
Instead of getting the description of the retrieved HelpItem on line 9 I get the description of the next HelpItem.
I.E. in an ArrayList of five HelpItem objects with the helpDescriptions "aaa", "bbb", "ccc", "ddd", "eee" clicking on "bbb" in the
list displays "bbb" and the information text associated with it. The title is set to "ccc".
On line 19 the same call to helpItem.getHelpDescription() returns the description field of the "bbb" object.
When moving through the list via a ViewPager the next object in the list has the same issue until I reach the end of the list,
where the correct helpDescription field is displayed. I can also move back to the start of the list and it will display the correct
helpDescription, but this is then lost when I move forward and backward through the list again.
Any ideas why this is happening? Thanks.
public class HelpFragment extends Fragment {
private HelpItem helpItem;
private TextView mHelpDetails;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
UUID helpItemId = (UUID) getArguments().getSerializable(EXTRA_HELP_ITEM_ID);
helpItem = HelpList.get(getActivity()).getHelpItem(helpItemId);
getActivity().setTitle(helpItem.getHelpDescription());
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
View userView = inflater.inflate(R.layout.fragment_help_item, parent, false);
mHelpDetails = (TextView) userView.findViewById(R.id.help_details);
String displayInfo = "";
if ((helpItem.getHelpDescription() != null) &&
(helpItem.getHelpInformation() != null)) {
displayInfo = helpItem.getHelpDescription() + "\n\n\n" +
helpItem.getHelpInformation();
mHelpDetails.setText(displayInfo);
Log.d(TAG, "3 " + helpItem.getHelpDescription() + " "
+ helpItem.getHelpInformation());
}
return userView;
}
}
..
public class HelpItem {
private UUID mId;
private String helpDescription;
private String helpInformation;
public HelpItem(String hDesc, String hInfo) {
mId = UUID.randomUUID();
helpDescription = hDesc;
helpInformation = hInfo;
}
public UUID getId() {
return mId;
}
public void setId(UUID id) {
mId = id;
}
#Override
public String toString() {
return helpDescription;
}
public String getHelpDescription() {
return helpDescription;
}
public void setHelpDescription(String hDescription) {
this.helpDescription = hDescription;
}
public String getHelpInformation() {
return helpInformation;
}
public void setHelpInformation(String hInformation) {
this.helpInformation = hInformation;
}
}
..
public class HelpListItemPagerActivity extends FragmentActivity {
private ViewPager mViewPager;
private ArrayList<HelpItem> mHelpList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewPager = new ViewPager(this);
mViewPager.setId(R.id.viewPager);
setContentView(mViewPager);
mHelpList = HelpList.get(this).getHelpList();
FragmentManager fragManager = getSupportFragmentManager();
mViewPager.setAdapter(new FragmentStatePagerAdapter(fragManager) {
#Override
public int getCount() {
return mHelpList.size();
}
#Override
public Fragment getItem(int position) {
HelpItem hItem = mHelpList.get(position);
return HelpFragment.newInstance(hItem.getId());
}
});
UUID helpItemId = (UUID)getIntent().getSerializableExtra(HelpFragment.EXTRA_HELP_ITEM_ID);
for (int i = 0; i < mHelpList.size(); i++) {
if (mHelpList.get(i).getId().equals(helpItemId)) {
mViewPager.setCurrentItem(i);
break;
}
}
}
}

Categories

Resources