Getting occasional NullPointerExceptions when setRefreshing(boolean) on SwipeRefreshLayout - android

I have a simple app that consists of one main activity and 3 fragments with ViewPager and Sliding tab layout. In each of the fragments I have SwipeRefreshLayouts.
The problem is sometimes when Android OS decides to kill my app and it crashes with that exception. It does not happen every time, though. I assume that sometimes the fragments are not created when I call the setRefreshing method and that is what is causing the error. Anyone having a suggestion on how to avoid this NPE?
This is the log:
12-29 23:31:41.770 29982-29982/koemdzhiev.com.stormy E/AndroidRuntime: FATAL EXCEPTION: main
Process: koemdzhiev.com.stormy, PID: 29982
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.widget.SwipeRefreshLayout.setRefreshing(boolean)' on a null object reference
at koemdzhiev.com.stormy.ui.MainActivity.toggleSwipeRefreshLayoutsOff(MainActivity.java:268)
at koemdzhiev.com.stormy.ui.MainActivity$3$2.run(MainActivity.java:224)
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:5292)
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)
MainActivity onCreate:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//-----------MY CODE STARTS HERE-----------------
//check if the user previously has seen the whats new message...
sharedPref = getPreferences(Context.MODE_PRIVATE);
editor = sharedPref.edit();
if (sharedPref.getInt(getString(R.string.saved_if_whats_new_seen), 1) != 0){
WhatsNewDialogCreator dialogCreator = new WhatsNewDialogCreator(this, sharedPref);
dialogCreator.show();
}
request = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY)
.setSmallestDisplacement(800)
.setFastestInterval(5 * 60 * 1000)
.setInterval(60 * 60 * 1000);
locationProvider = new ReactiveLocationProvider(this);
//subscribe for background location updates...
if(isNetworkAvailable()) {
startBackgroundUpdates();
}
mainActivityLayout = (LinearLayout)findViewById(R.id.main_activity_layout);
changeWindowTopColor();
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);
if(isFirstTimeLaunchingTheApp) {
Log.d(TAG, "onCreate getLocation");
getLocation();
}
}
ViewPagerAdapter:
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;
}
}
getLocation Method:
public void getLocation() {
Log.d(TAG,"getLocation initiated...");
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (isNetworkAvailable()) {
//check if the if the location services are enabled
if( !isLocationServicesEnabled()) {
alertForNoLocationEnabled();
}else {
LocationRequest oneTimeOnStartRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setNumUpdates(1)
.setInterval(0);
onlyFirstTimeSubscription = locationProvider.getUpdatedLocation(oneTimeOnStartRequest)
.subscribe(new Action1<Location>() {
#Override
public void call(Location location) {
Log.d(TAG, "Getting first location updates...");
MainActivity.this.latitude = location.getLatitude();
MainActivity.this.longitude = location.getLongitude();
reverseGeocodeObservable = locationProvider
.getReverseGeocodeObservable(location.getLatitude(), location.getLongitude(), 1);
getLocationName();
//check, only on create get location calls getForecast...
if (isFirstTimeLaunchingTheApp) {
getForecast(latitude, longitude);
}
onlyFirstTimeSubscription.unsubscribe();
}
});
}
} else {
alertForNoInternet();
Log.d(TAG, "Alert No Internet" + 366);
}
}
getForecastmethod (this is the method where the NPE is thrown)
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 = "API_KEY";
String forecast = "https://api.forecast.io/forecast/" + API_KEY + "/" + latitude + "," + longitude + "?units=auto";
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();
}
});
//on response from the server cansel the noResponseFromServer task
//on response from the server cansel the noResponseFromServer task
Log.d(TAG,"OnFailure_ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
alertUserAboutError();
}
//when the call to the Okhttp library finishes, than calls this method:
#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)...");
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);
}
//on response from the server cansel the noResponseFromServer task
Log.d(TAG,"OnResponse_ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
}
});
} else {
toggleSwipeRefreshLayoutsOff();
alertForNoInternet();
Log.d(TAG, "Alert No Internet" + 220);
//is there is no internet cancel the noResponseFromServer task
Log.d(TAG, "No internet _ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
}
}

I have the same situation as yours when I use Fragment&ViewPager...
here is the way I figure it out:
if (swipeRefreshLayout != null) {
swipeRefreshLayout.setRefreshing(false);
}
Ps:
when I use SwipeRefreshLayout it an activity,this exception will not happen. Can someone provide better answers?

Related

How to make progress dialog in fragment tab in Android?

I have MainActivity which added two fragment tab namely "tab1 and "tab2.tab 1 sends some request to server during this process I Want to show a progress dialog but when I do this through a error message "android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application" and also have some implementation of Broadcast receiver in tab 1 fragment which also through error "unable to register receiver"
Progress dialog code:
public class DialogUtils {
public static ProgressDialog showProgressDialog(Context context, String message) {
ProgressDialog m_Dialog = new ProgressDialog(context);
m_Dialog.setMessage(message);
m_Dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
m_Dialog.setCancelable(false);
m_Dialog.show();
return m_Dialog;
}
}
Mainactivity code:
m_TabLayout = (TabLayout) findViewById(R.id.tab_layout);// finding Id of tablayout
m_ViewPager = (ViewPager) findViewById(R.id.pager);//finding Id of ViewPager
m_TabLayout.addTab(m_TabLayout.newTab().setText("Deals"));// add deal listin tab
m_TabLayout.addTab(m_TabLayout.newTab().setText("Stories"));
m_TabLayout.setTabGravity(TabLayout.GRAVITY_FILL);// setting Gravity of Tab
CDealMainListingPager m_oDealMainScreenPager = new CDealMainListingPager(getSupportFragmentManager(), m_TabLayout.getTabCount());
m_ViewPager.setAdapter(m_oDealMainScreenPager);// adiing adapter to ViewPager
m_ViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(m_TabLayout));// performing action of page changing
m_TabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
m_ViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
and tab1 fragment tab code:
public static final String TAG = CDealAppListing.class.getSimpleName();
public static final int m_TRANSACTION_SUCCESSFUL = 0;
public static String m_szMobileNumber;//declaring String mobile number variable
public static String m_szEncryptedPassword;//declaring string password variable
public static String sz_RecordCount;// //declaring String record count variable variable
public static String sz_LastCount;//declaring String lastcount variable
private static ListView m_ListView;// declaring Listview variable..
private static CDealAppListingAdapter m_oAdapter;// declaring DealListingAdapter..
public CDealAppDatastorage item;// declaring DealAppdataStorage
public View mFooter;
public AppCompatButton m_BtnRetry;
/*This Broadcast receiver will listen network state accordingly
which enable or disable create an account button*/
private final BroadcastReceiver m_oInternetChecker = new BroadcastReceiver() {// creating broadcast to receive otp sent by server from Inbox...
#Override
public void onReceive(Context context, Intent intent) {// on receive method to read OTP sent by server
changeButtonState();// check whether edit text is empty or not
}
};
RequestQueue requestQueue;
JsonObjectRequest jsonObjectRequest;
private ArrayList<CDealAppDatastorage> s_oDataset;// declaring Arraylist variable
private int[] m_n_FormImage;//declaring integer array varaible
private View m_Main;//declaring View variable
private int m_n_DefaultRecordCount = 5;// intiallly record count is 5.
private int m_n_DeafalutLastCount = 0;//initally lastcount is 0.
private SwipeRefreshLayout mSwipeRefresh;
private ProgressDialog m_Dialog;
private boolean bBottomOfView;
private LinearLayout m_NoInternetWarning;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
m_Main = inflater.inflate(R.layout.deal_listing, container, false);//intialize mainLayout
Log.i(TAG, "OnCreateView.........");
init();
return m_Main;
}
#Override
public void onResume() {
super.onResume();
Log.i(TAG, "onResume.........");
/*Registered Broadcast receiver*/
IntentFilter m_intentFilter = new IntentFilter();// creating object of Intentfilter class user for defining permission
m_intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");// action to check Internet connection
getActivity().registerReceiver(m_oInternetChecker, m_intentFilter);// register receiver....
getDetails();
}
public void changeButtonState() {
if (NetworkUtil.isConnected(getActivity())) {
m_BtnRetry.setEnabled(true);
m_BtnRetry.setBackgroundColor(Color.rgb(0, 80, 147));// set background color on eabled
} else {
m_BtnRetry.setEnabled(false);
m_BtnRetry.setBackgroundColor(Color.rgb(192, 192, 192));// color of login button
}
}
private void getDetails() {// get details of user from shared preference...
CLoginSessionManagement m_oSessionManagement = new CLoginSessionManagement(getActivity());// crating object of Login Session
HashMap<String, String> user = m_oSessionManagement.getLoginDetails();// get String from Login Session
m_szMobileNumber = user.get(CLoginSessionManagement.s_szKEY_MOBILE).trim();// getting password from saved preferences..........
m_szEncryptedPassword = user.get(CLoginSessionManagement.s_szKEY_PASSWORD).trim();// getting mobile num from shared preferences...
sz_RecordCount = String.valueOf(m_n_DefaultRecordCount);// increment of record count
m_n_DeafalutLastCount = 0;
sz_LastCount = String.valueOf(m_n_DeafalutLastCount);// increment of last count...
s_oDataset = new ArrayList<>();// making object of Arraylist
if (NetworkUtil.isConnected(getActivity())) {
m_NoInternetWarning.setVisibility(View.GONE);
postDealListingDatatoServer();// here sending request in onCreate
} else {
mSwipeRefresh.setVisibility(View.GONE);
m_NoInternetWarning.setVisibility(View.VISIBLE);
m_BtnRetry.setEnabled(false);
m_BtnRetry.setBackgroundColor(Color.rgb(192, 192, 192));// color of login button
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy...............");
getActivity().unregisterReceiver(m_oInternetChecker);// unregistaer broadcast receiver.
}
private void init() {// initialize controls
m_NoInternetWarning = (LinearLayout) m_Main.findViewById(R.id.no_internet_warning);
m_BtnRetry = (AppCompatButton) m_Main.findViewById(R.id.btn_retry);
m_BtnRetry.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
retryRequest(v);
}
});
m_ListView = (ListView) m_Main.findViewById(R.id.dealList);// findind Id of Listview
m_ListView.setFadingEdgeLength(0);
m_ListView.setOnScrollListener(this);
/*Swipe to refresh code*/
mSwipeRefresh = (SwipeRefreshLayout) m_Main.findViewById(R.id.swipe);
mSwipeRefresh.setColorSchemeResources(R.color.refresh_progress_1);
mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
/*Here check net connection avialable or not */
if (NetworkUtil.isConnected(getActivity())) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
sz_RecordCount = String.valueOf(m_n_DefaultRecordCount);// increment of record count
m_n_DeafalutLastCount = 0;
sz_LastCount = String.valueOf(m_n_DeafalutLastCount);// increment of last count...
swipeData();
}
}, 3500);
} else {
m_NoInternetWarning.setVisibility(View.VISIBLE);
mSwipeRefresh.setVisibility(View.GONE);
if (mSwipeRefresh.isRefreshing()) {
mSwipeRefresh.setRefreshing(false);
}
}
}
});
m_n_FormImage = new int[]{// defining Images in Integer array
R.drawable.amazon,
R.drawable.whatsapp,
R.drawable.zorpia,
R.drawable.path,
R.drawable.app_me,
R.drawable.evernote,
R.drawable.app_me};
}
public void retryRequest(View v) {
if (NetworkUtil.isConnected(getActivity())) {
m_BtnRetry.setEnabled(true);
m_BtnRetry.setBackgroundColor(Color.rgb(0, 80, 147));// set background color on eabled
sz_RecordCount = String.valueOf(m_n_DefaultRecordCount);// increment of record count
m_n_DeafalutLastCount = 0;
sz_LastCount = String.valueOf(m_n_DeafalutLastCount);// increment of last count...
postDealListingDatatoServer();
} else {
m_BtnRetry.setEnabled(false);
m_BtnRetry.setBackgroundColor(Color.rgb(192, 192, 192));// color of login button
}
}
/*This is new changes in code ....using Volley instead of AsynkTask*/
/*This method send request to server for deallisting*/
// this method send request to server for deal list....
public void postDealListingDatatoServer() {
try {
String json;
// 3. build jsonObject
final JSONObject jsonObject = new JSONObject();// making object of Jsons.
jsonObject.put("agentCode", m_szMobileNumber);// put mobile number
jsonObject.put("pin", m_szEncryptedPassword);// put password
jsonObject.put("recordcount", sz_RecordCount);// put record count
jsonObject.put("lastcountvalue", sz_LastCount);// put last count
System.out.println("Record Count:-" + sz_RecordCount);
System.out.println("LastCount:-" + sz_LastCount);
// 4. convert JSONObject to JSON to String
json = jsonObject.toString();// convert Json object to string
Log.i(TAG, "Server Request:-" + json);
m_Dialog = DialogUtils.showProgressDialog(getActivity().getApplicationContext(), "Loading...");
final String m_DealListingURL = "http://202.131.144.132:8080/json/metallica/getDealListInJSON";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, m_DealListingURL, jsonObject, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i(TAG, "Server Response:-" + response);
m_Dialog.dismiss();
try {
int nResultCodeFromServer = Integer.parseInt(response.getString("resultcode"));
if (nResultCodeFromServer == m_TRANSACTION_SUCCESSFUL) {
JSONArray posts = response.optJSONArray("dealList");// get Deal list in array from response
s_oDataset.clear();
for (int i = 0; i < posts.length(); i++) {// loop for counting deals from server
JSONObject post = posts.getJSONObject(i);// counting deal based on index
item = new CDealAppDatastorage();// creating object of DealAppdata storage
item.setM_szHeaderText(post.getString("dealname"));// get deal name from response
item.setM_szsubHeaderText(post.getString("dealcode"));// get dealcode from response
item.setM_szDealValue(post.getString("dealvalue"));// get deal value from response
item.setM_n_Image(m_n_FormImage[i]);//set Image Index wise(Dummy)
s_oDataset.add(item);// add all items in ArrayList
}
if (!s_oDataset.isEmpty()) {// condition if data in arraylist is not empty
m_oAdapter = new CDealAppListingAdapter(getActivity(), s_oDataset);// create adapter object and add arraylist to adapter
m_ListView.setAdapter(m_oAdapter);//adding adapter to recyclerview
m_NoInternetWarning.setVisibility(View.GONE);
mSwipeRefresh.setVisibility(View.VISIBLE);
} else {
m_ListView.removeFooterView(mFooter);// else Load buttonvisibility set to Gone
}
}
if (response.getString("resultdescription").equalsIgnoreCase("Connection Not Available")) {//server based conditions
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "Connection Lost !", getActivity());
} else if (response.getString("resultdescription").equalsIgnoreCase("Deal List Not Found")) {// serevr based conditions .....
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "No more deals available", getActivity());
} else if (response.getString("resultdescription").equalsIgnoreCase("Technical Failure")) {
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "Technical Failure", getActivity());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Server error:-" + error);
m_Dialog.dismiss();
if (error instanceof TimeoutError) {
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "Connection lost ! Please try again", getActivity());
} else if (error instanceof NetworkError) {
CSnackBar.getInstance().showSnackBarError(m_Main.findViewById(R.id.mainLayout), "No internet connection", getActivity());
mSwipeRefresh.setVisibility(View.GONE);
m_NoInternetWarning.setVisibility(View.VISIBLE);
}
}
});
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(jsonObjectRequest);
} catch (JSONException e) {
e.printStackTrace();
}
}
Step1: Change DialogUtils class:
public static ProgressDialog showProgressDialog(Activity activity, String message) {
ProgressDialog m_Dialog = new ProgressDialog(activity);
m_Dialog.setMessage(message);
m_Dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
m_Dialog.setCancelable(false);
m_Dialog.show();
return m_Dialog;
}
Step2: Change the postDealListingDatatoServer() method.
m_Dialog = DialogUtils.showProgressDialog(getActivity(), "Loading...");
Step3: About broadcast receiver. Please register at the onResume() method and unregister at the onPause() method.
public static ProgressDialog showProgressDialog(Context context, String message) {
ProgressDialog m_Dialog = new ProgressDialog(context);
m_Dialog.setMessage(message);
m_Dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
m_Dialog.setCancelable(false);
if (!((Activity) context).isFinishing()) {
m_Dialog.show();
}
return m_Dialog;
}
To dismiss dialog:
if ((m_Dialog!= null) && m_Dialog.isShowing())
m_Dialog.dismiss();
Check if fragment is visible or not.
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (this.isVisible()) {
// If we are becoming invisible, then...
if (!isVisibleToUser) {
}
} else {
}
}
}

I get Null Pointer Exception when Android OS kills my app

I have a simple weather app that uses fragments to display the current, hourly and daily weather. I have noticed that when I open a heavy app (game) and then I try to open the my app it crashes with the null pointer exception because a fragment (maybe all of the 3) is not attached to the fragment manager.
I have experienced this crash many times but with no luck finding a solution to the problem. I have including a if-else statement to check if the fragment is attached (see the log). Why might I be getting the NPE?
Here is my log:
Getting first location updates...
01-22 22:02:05.362 14082-14082/koemdzhiev.com.stormy V/MainActivity: Locality: Aberdeen, CountryName United Kingdom
01-22 22:02:05.749 14082-14115/koemdzhiev.com.stormy D/MainActivity: OnResponse_ scheduledFuture is CANCELED
01-22 22:02:05.757 14082-14082/koemdzhiev.com.stormy D/MainActivity: isSuccessful - run on UNI threth (update display)...
01-22 22:02:05.787 14082-14082/koemdzhiev.com.stormy D/MainActivity: mCurrent fragment is NOT attached!
01-22 22:02:05.788 14082-14082/koemdzhiev.com.stormy D/AndroidRuntime: Shutting down VM
01-22 22:02:05.789 14082-14082/koemdzhiev.com.stormy E/AndroidRuntime: FATAL EXCEPTION: main
Process: koemdzhiev.com.stormy, PID: 14082
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference
at android.widget.Toast.<init>(Toast.java:103)
at android.widget.Toast.makeText(Toast.java:260)
at koemdzhiev.com.stormy.ui.Hourly_forecast_fragment.setUpHourlyFragment(Hourly_forecast_fragment.java:128)
at koemdzhiev.com.stormy.ui.MainActivity$3$3.run(MainActivity.java:247)
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)
The problematic method in MainActivity:
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 = "API_KEY";
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();
}
});
//on response from the server cansel the noResponseFromServer task
//on response from the server cansel the noResponseFromServer task
Log.d(TAG,"OnFailure_ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
alertUserAboutError();
}
//when the call to the Okhttp library finishes, than calls this method:
#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)...");
if(mCurrent_forecast_fragment.isAdded()){
Log.d(TAG, "mCurrent fragment is attached!");
mCurrent_forecast_fragment.updateDisplay();
}else{
Toast.makeText(MainActivity.this, "mCurrent is not attached!", Toast.LENGTH_SHORT).show();
Log.d(TAG, "mCurrent fragment is NOT attached!");
adapter = null;
adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles, Numboftabs, mCurrent_forecast_fragment,
mHourly_forecast_fragment, mDaily_forecast_fragment);
}
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);
}
//on response from the server cansel the noResponseFromServer task
Log.d(TAG,"OnResponse_ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
}
});
} else {
toggleSwipeRefreshLayoutsOff();
alertForNoInternet();
Log.d(TAG, "Alert No Internet" + 220);
//is there is no internet cancel the noResponseFromServer task
Log.d(TAG, "No internet _ scheduledFuture is CANCELED");
mScheduledFuture.cancel(true);
}
}
This is mCurrent fragment code (line 247 is this code:
mHourly_forecast_fragment.setUpHourlyFragment (in main activity))
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());
// Log.d(mActivity.getClass().getSimpleName(),"OnCreateFragment");
}
#Override
public void onResume() {
super.onResume();
Log.d(TAG, "OnResume - Current Fragment called");
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;
}
#Override
public void onDestroyView() {
super.onDestroyView();
Log.d(TAG, "OnDestroyView - Current Fragment called");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "OnDestroy - Current Fragment called");
}
public void updateDisplay() {
if(mActivity != 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();
}
}
#Override
public void onSaveInstanceState(Bundle outState) {
}
}
Line 128 in Hourly Activity:
public void setUpHourlyFragment(){
if (mActivity != null) {
// Toast.makeText(mActivity, getString(R.string.network_unavailable_message), Toast.LENGTH_LONG).show();
//set to null to reset the old one and set a new adapter bellow...
mListView.setAdapter(null);
Hour[] hourlyForecast = mActivity.mForecast.getHourlyForecast();
mHours = Arrays.copyOf(hourlyForecast, hourlyForecast.length, Hour[].class);
HourListAdapter adapter = new HourListAdapter(mActivity, mHours);
mListView.setEmptyView(mEmptyTextView);
mListView.setAdapter(adapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
Hour h = mHours[position];
String time = h.getHour();
String temperature = h.getTemperature()+"";
String summary = h.getSummary();
String message = String.format("At %s it will be %s and %s",time,temperature,summary);
Toast.makeText(mActivity, message, Toast.LENGTH_LONG).show();
//play animations
YoYo.with(Techniques.Shake).duration(200).playOn(view);
}
});
}else{
//LINE 128 bellow...
Toast.makeText(getActivity(),"Main Activity is null in Hourly Fragment",Toast.LENGTH_LONG).show();
}
}
}
Please use instance of mActivity instead of getActivity() inside Toast (Line : 128).
`Toast.makeText(getActivity(),"Main Activity is null in Hourly Fragment",Toast.LENGTH_LONG).show();}`
As for extra check, provide a null check before making Toast on mActivity.

ViewPager showing data wrong with RecyclerView

I am trying to show holidays per year(fetched from web service using volley) and for display holiday I used RecyclerView. Following is my code:
It overall working but some issues exist in this code.
I don't know what I am doing wrong here ?
public class ShowHolidaysPage extends AppCompatActivity implements ViewPager.OnPageChangeListener{
private static final int PAGE_LEFT = 0;
private static final int PAGE_MIDDLE = 1;
private static final int PAGE_RIGHT = 2;
HolidayFragment leftPage = null,middlePage = null,rightPage = null;
List<HolidayFragment> fList = new ArrayList<HolidayFragment>();
enter code here
#Override
protected void onCreate(Bundle savedInstanceState) {
fList.add(HolidayFragment.newInstance("" + (year1 - 1), authToken, deviceId,yearList));
fList.add(HolidayFragment.newInstance("" + year1, authToken, deviceId,yearList));
fList.add(HolidayFragment.newInstance("" + (year1 + 1), authToken, deviceId,yearList));
leftPage = fList.get(PAGE_LEFT);
middlePage = fList.get(PAGE_MIDDLE);
rightPage = fList.get(PAGE_RIGHT);
init();
pageAdapter = new MyPageAdapter(getSupportFragmentManager(), fList);
pager = (ViewPager)findViewById(R.id.holiday_pager);
pager.setAdapter(pageAdapter);
pager.setOnPageChangeListener(this);
pager.setCurrentItem(1, false);
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
mSelectedPageIndex = position;
}
#Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
final int oldLeftIndex = leftPage.getIndex();
final int oldMiddleIndex = middlePage.getIndex();
final int oldRightIndex = rightPage.getIndex();
if (mSelectedPageIndex == PAGE_LEFT) {
currentYear.add(Calendar.YEAR, -1);
Calendar prevYear = Calendar.getInstance();
prevYear.setTime(currentYear.getTime());
prevYear.add(Calendar.YEAR, -1);
Calendar nextYear = Calendar.getInstance();
nextYear.setTime(currentYear.getTime());
nextYear.add(Calendar.YEAR, 1);
leftPage.setIndex(oldLeftIndex - 1, prevYear);
middlePage.setIndex(oldLeftIndex, currentYear);
rightPage.setIndex(oldMiddleIndex, nextYear);
}
else if (mSelectedPageIndex == PAGE_RIGHT) {
currentYear.add(Calendar.YEAR, 1);
Calendar prevYear = Calendar.getInstance();
prevYear.setTime(currentYear.getTime());
prevYear.add(Calendar.YEAR, -1);
Calendar nextYear = Calendar.getInstance();
nextYear.setTime(currentYear.getTime());
nextYear.add(Calendar.YEAR, 1);
leftPage.setIndex(oldMiddleIndex, prevYear);
middlePage.setIndex(oldRightIndex, currentYear);
rightPage.setIndex(oldRightIndex + 1, nextYear);
}
pager.setCurrentItem(1, false);
}
}
class MyPageAdapter extends FragmentStatePagerAdapter {
private List<HolidayFragment> fragments;
public MyPageAdapter(FragmentManager fm, List<HolidayFragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return this.fragments.get(position);
}
#Override
public int getCount() {
return this.fragments.size();
}
}
}
this method is in holiday fragment:
public void setIndex(int index,Calendar year1) {
this.index = index;
if(year1 != null) {
year = ""+year1.get(Calendar.YEAR);
if(year.equals(""+year1.get(Calendar.YEAR))) {
String year = "" + year1.get(Calendar.YEAR);
yearView.setText(year);
if(networkCall.getRequestQueue()!= null) {
networkCall.getRequestQueue().cancelAll(getTag());
}
getHolidays(authtoken, deviceId, yearView.getText().toString());
}
}
}
public void getHolidays(String authToken, String deviceID, final String year) {
if(recyclerView != null) {
if (recyclerView.getVisibility() == View.VISIBLE) {
recyclerView.setVisibility(View.GONE);
}
}
if(holidayNotAvailable != null) {
if (holidayNotAvailable.getVisibility() == View.VISIBLE) {
holidayNotAvailable.setVisibility(View.GONE);
}
}
if(yearList==null){
yearList=new ArrayList<Integer>();
}
if(!yearList.contains(Integer.parseInt(year))) {
progressbar.setVisibility(View.VISIBLE);
networkCall = NetworkCall.getInstance(getActivity().getApplicationContext());
String url = url;
url += "&year=" + year;
JsonObjectRequest jsonObject = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject jsonObject) {
yearList.add(Integer.parseInt(year));
try {
Map<String, String> holidaysMap = new Gson().fromJson(jsonObject + "", new TypeToken<SortedMap<String, String>>() {
}.getType());
progressbar.setVisibility(View.GONE);
if (holidaysMap.size() != 0) {
if (holidayNotAvailable.getVisibility() == View.VISIBLE) {
holidayNotAvailable.setVisibility(View.GONE);
}
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
recyclerView.setVisibility(View.VISIBLE);
recyclerView.setLayoutManager(layoutManager);
adapter = new HolidayAdapter(holidaysMap, year);
recyclerView.setAdapter(adapter);
} else {
progressbar.setVisibility(View.GONE);
recyclerView.setVisibility(View.GONE);
holidayNotAvailable.setVisibility(View.VISIBLE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
String msg = "";
if (volleyError instanceof TimeoutError || volleyError instanceof NoConnectionError) {
msg = "Time out Error! Please try again later";
} else if (volleyError instanceof AuthFailureError) {
startActivity(new Intent(getActivity().getApplicationContext(), IntroActivity.class));
} else if (volleyError instanceof ServerError) {
msg = "Server Error! Please try again later";
} else if (volleyError instanceof NetworkError) {
msg = "Network Error! Please try again later";
} else if (volleyError instanceof ParseError) {
msg = "Parser Error! Please try again later";
}
if (!EwUtils.isNullString(msg)) {
if (getActivity() != null) {
Toast.makeText(getActivity().getApplicationContext(), msg, Toast.LENGTH_SHORT);
}
}
}
});
networkCall.addToRequestQueue(jsonObject);
}
}
Its shows pages on swipe left or right correctly but following two issues are exist there now:
Three pages forms at a time so when we swipe left or right it again call the get holiday method which create view while it is already created, So I am unable to know why it recreate the page.
when we swipe fast then it shows data wrong.It seems it puts data of another request in another fragment.
I already tried it by using pager.setOffscreenPageLimit(1); but is not works and recreate the fragment when it comes to idle state.
I don't know what I am doing wrong here.So please guide me about this.
By default, your ViewPager retains one page left and one page right from the active (current) fragment.
This is, when you go to the third the first is destroyed and the fouth is created like a cache for a better user experience.
You can change your limit calling the method of ViewPager setOffscreenPageLimit
Regarding to your wrong data: I recommend you to separate the logic in different instances from this class. The problem is that the requests are made asynchronously so you change the page before having the response back and it seems to be messy calling the same piece of code.
I hope this would help you

ListView: how to notify the user about new fetched data with sound and vibration?

I've added my MainActivity below, the application fetches data from a database and refreshes automatically and on swipe down.
My question is, how on earth can it notify the user about "new" fetched inserts via sound and vibration?
To be more specific regarding the definition of "new inserts", the application starts with 0 data in it, once refreshed a php call from the database gets a new JSON string and is decoded in the app and appears on the listview.
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
private int mInterval = 5000; // 5 seconds by default, can be changed later
private Handler mHandler;
private String TAG = MainActivity.class.getSimpleName();
private String URL = "http://10.0.0.2:0080/stringtest2.php?offset=";
private SwipeRefreshLayout swipeRefreshLayout;
private ListView listView;
private SwipeListAdapter adapter;
private List<Order> orderList;
// initially offset will be 0, later will be updated while parsing the json
private int offSet = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
//RelativeLayout.LayoutParams layout_description = new RelativeLayout.LayoutParams(50,10);
//Rl.setLayoutParams(layout_description);
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
orderList = new ArrayList<>();
adapter = new SwipeListAdapter(this, orderList);
listView.setAdapter(adapter);
swipeRefreshLayout.setOnRefreshListener(this);
/**
* Showing Swipe Refresh animation on activity create
* As animation won't start on onCreate, post runnable is used
*/
swipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
fetchOrders();
}
}
);
mHandler = new Handler();
startRepeatingTask();
}
/**
* This method is called when swipe refresh is pulled down
*/
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
//updateStatus(); //this function can change value of mInterval.
mHandler.postDelayed(mStatusChecker, mInterval);
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
//added code start here
Runnable mAutoRefreshRunnable = new Runnable() {
#Override
public void run() {
fetchOrders();
mHandler.postDelayed(mAutoRefreshRunnable, 60000);
}
};
#Override
protected void onResume() {
super.onResume();
mHandler.postDelayed(mAutoRefreshRunnable, 60000);
}
#Override
protected void onPause(){
super.onPause();
mHandler.removeCallbacks(mAutoRefreshRunnable);
}
//added code ends here
#Override
public void onRefresh() {
fetchOrders();
}
/**
* Fetching movies json by making http call
*/
private void fetchOrders() {
// showing refresh animation before making http call
swipeRefreshLayout.setRefreshing(true);
// appending offset to url
String url = URL + offSet;
// Volley's json array request object
JsonArrayRequest req = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
if (response.length() > 0) {
// looping through json and adding to order list
for (int i = 0; i < response.length(); i++) {
try {
JSONObject orderObj = response.getJSONObject(i);
int rank = orderObj.getInt("rank");
String title = orderObj.getString("title");
Order m = new Order(rank, title);
orderList.add(0, m);
// updating offset value to highest value
if (rank >= offSet)
offSet = rank;
} catch (JSONException e) {
Log.e(TAG, "JSON Parsing error: " + e.getMessage());
}
}
adapter.notifyDataSetChanged();
}
// stopping swipe refresh
swipeRefreshLayout.setRefreshing(false);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Server Error: " + error.getMessage());
Toast.makeText(getApplicationContext(), "Can't connect to database", Toast.LENGTH_LONG).show();
// stopping swipe refresh
swipeRefreshLayout.setRefreshing(false);
}
});
// Adding request to request queue
MyApplication.getInstance().addToRequestQueue(req);
}
}
After you fetch new data, there is a place you need to call notifyDataSetChanged() to let the listview update its content.
right after that call, you can use Vibrator to start a vibration
Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
// Vibrate for 500 milliseconds
v.vibrate(500);
see: http://developer.android.com/reference/android/os/Vibrator.html
To play sound, you need a MediaPlayer:
MediaPlayer mp = MediaPlayer.create(this, yourSoundFile);
mp.start();

Android: Where and how to auto refresh listview (I have the refresh function)

This is my MainActivity, I really need help on creating a function that will autorefresh the listview every minute
In my MainActivity I have this code:
//This method is called when swipe refresh is pulled down
#Override
public void onRefresh() {
fetchOrders();
}
I've read a few articles about the handler, I gotta say I have no idea where to put the handler's code, therefore if you can give me a hand and post my full MainActivity with that additional desired code, it would be more than appreciated
Thanks in advance!
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
private int mInterval = 5000; // 5 seconds by default, can be changed later
private Handler mHandler;
private String TAG = MainActivity.class.getSimpleName();
private String URL = "http://troyka.esy.es/troyka/orders.php";
private SwipeRefreshLayout swipeRefreshLayout;
private ListView listView;
private SwipeListAdapter adapter;
private List<Order> orderList;
// initially offset will be 0, later will be updated while parsing the json
private int offSet = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
//RelativeLayout.LayoutParams layout_description = new RelativeLayout.LayoutParams(50,10);
//Rl.setLayoutParams(layout_description);
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
orderList = new ArrayList<>();
adapter = new SwipeListAdapter(this, orderList);
listView.setAdapter(adapter);
swipeRefreshLayout.setOnRefreshListener(this);
/**
* Showing Swipe Refresh animation on activity create
* As animation won't start on onCreate, post runnable is used
*/
swipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
fetchOrders();
}
}
);
mHandler = new Handler();
startRepeatingTask();
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
//updateStatus(); //this function can change value of mInterval.
mHandler.postDelayed(mStatusChecker, mInterval);
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
/**
* This method is called when swipe refresh is pulled down
*/
#Override
public void onRefresh() {
fetchOrders();
}
/**
* Fetching movies json by making http call
*/
private void fetchOrders() {
// showing refresh animation before making http call
swipeRefreshLayout.setRefreshing(true);
// appending offset to url
String url = URL + offSet;
// Volley's json array request object
JsonArrayRequest req = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
if (response.length() > 0) {
// looping through json and adding to order list
for (int i = 0; i < response.length(); i++) {
try {
JSONObject orderObj = response.getJSONObject(i);
int rank = orderObj.getInt("rank");
String title = orderObj.getString("title");
Order m = new Order(rank, title);
orderList.add(0, m);
// updating offset value to highest value
if (rank >= offSet)
offSet = rank;
} catch (JSONException e) {
Log.e(TAG, "JSON Parsing error: " + e.getMessage());
}
}
adapter.notifyDataSetChanged();
}
// stopping swipe refresh
swipeRefreshLayout.setRefreshing(false);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Server Error: " + error.getMessage());
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
// stopping swipe refresh
swipeRefreshLayout.setRefreshing(false);
}
});
// Adding request to request queue
MyApplication.getInstance().addToRequestQueue(req);
}
}
You can do that by added a delayed task to Handler. Here is the full code:
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
private int mInterval = 5000; // 5 seconds by default, can be changed later
private Handler mHandler;
private String TAG = MainActivity.class.getSimpleName();
private String URL = "http://troyka.esy.es/troyka/orders.php";
private SwipeRefreshLayout swipeRefreshLayout;
private ListView listView;
private SwipeListAdapter adapter;
private List<Order> orderList;
// initially offset will be 0, later will be updated while parsing the json
private int offSet = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.listView);
//RelativeLayout.LayoutParams layout_description = new RelativeLayout.LayoutParams(50,10);
//Rl.setLayoutParams(layout_description);
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
orderList = new ArrayList<>();
adapter = new SwipeListAdapter(this, orderList);
listView.setAdapter(adapter);
swipeRefreshLayout.setOnRefreshListener(this);
/**
* Showing Swipe Refresh animation on activity create
* As animation won't start on onCreate, post runnable is used
*/
swipeRefreshLayout.post(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
fetchOrders();
}
}
);
mHandler = new Handler();
startRepeatingTask();
}
Runnable mStatusChecker = new Runnable() {
#Override
public void run() {
//updateStatus(); //this function can change value of mInterval.
mHandler.postDelayed(mStatusChecker, mInterval);
}
};
void startRepeatingTask() {
mStatusChecker.run();
}
void stopRepeatingTask() {
mHandler.removeCallbacks(mStatusChecker);
}
//added code start here
Runnable mAutoRefreshRunnable = new Runnable() {
#Override
public void run() {
fetchOrders()
mHandler.postDelayed(mAutoRefreshRunnable, 1000);
}
};
#Override
protected void onResume() {
mHandler.postDelayed(mAutoRefreshRunnable, 1000);
}
#Override
protected void onPause() {
mHandler.removeCallbacks(mAutoRefreshRunnable);
}
//added code ends here
/**
* This method is called when swipe refresh is pulled down
*/
#Override
public void onRefresh() {
fetchOrders();
}
/**
* Fetching movies json by making http call
*/
private void fetchOrders() {
// showing refresh animation before making http call
swipeRefreshLayout.setRefreshing(true);
// appending offset to url
String url = URL + offSet;
// Volley's json array request object
JsonArrayRequest req = new JsonArrayRequest(url,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
if (response.length() > 0) {
// looping through json and adding to order list
for (int i = 0; i < response.length(); i++) {
try {
JSONObject orderObj = response.getJSONObject(i);
int rank = orderObj.getInt("rank");
String title = orderObj.getString("title");
Order m = new Order(rank, title);
orderList.add(0, m);
// updating offset value to highest value
if (rank >= offSet)
offSet = rank;
} catch (JSONException e) {
Log.e(TAG, "JSON Parsing error: " + e.getMessage());
}
}
adapter.notifyDataSetChanged();
}
// stopping swipe refresh
swipeRefreshLayout.setRefreshing(false);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Server Error: " + error.getMessage());
Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show();
// stopping swipe refresh
swipeRefreshLayout.setRefreshing(false);
}
});
// Adding request to request queue
MyApplication.getInstance().addToRequestQueue(req);
}
}

Categories

Resources