I have an app that reads and display data from a weather API as show below.
Now those data you see in the RecyclerView are displayed via a Fragment. What happens is when I click the Forecast button in the toolbar the web service service is running again. Which means that the Fragment is added in the stack/click.
So here is my logic how to fix that. If the stack is null then add the Fragment. If not then don't.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.forecast) {
String tag = "forecastFragment";
Fragment f = getSupportFragmentManager().findFragmentByTag(tag);
if (f == null) {
ForecastFragment forecastFragment = new ForecastFragment();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.main_content, forecastFragment, "forecastfragment");
ft.addToBackStack("added today current");
forecastFragment.setArguments(b);
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
ft.commit();
} else{
getSupportFragmentManager().findFragmentById(R.id.main_content);
}
}
return super.onOptionsItemSelected(item);
}
Here is what I did, but still the web service is running every time I click the Forecast button.
Any ideas?
Here is my Webservice that is run by the ForecastFragment.
class ForecastFragment extends Fragment {
private static final String FORECAST_KEY = "forecast";
public static String URL=
"http://api.openweathermap.org/data/2.5/forecast/daily?";
EditText editText;
public static String BASE_URL= "";
private String IMG_URL ="http://api.openweathermap.org/img/w/";
private String retrievedLat;
private String retrievedLog;
private RecyclerView mRecyclerView;
ImageView imageView;
public ArrayList<Model> modelList;
private Model m;
WeekForecastAdapter adapter;
public ForecastFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_forecast, container, false);
retrievedLat = getArguments().getString("lat");
retrievedLog = getArguments().getString("log");
//http://api.openweathermap.org/data/2.5/forecast/daily?lat=35&lon=139&units=metric&cnt=10&mode=json&appid=d48708e1e4d8e2b60da14778acd8d56a
BASE_URL = URL +"lat="+retrievedLat+"&lon="+retrievedLog+"&units=metric&cnt=10&mode=json&appid=d48708e1e4d8e2b60da14778acd8d56a";
modelList = new ArrayList<>();
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerView = (RecyclerView)rootView.findViewById(R.id.week_forecast_recycler_view);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(linearLayoutManager);
adapter = new WeekForecastAdapter(getActivity(),modelList);
mRecyclerView.setAdapter(adapter);
if(savedInstanceState!=null){
ArrayList<Model> items = savedInstanceState.getParcelableArrayList(FORECAST_KEY);
modelList = savedInstanceState.getParcelableArrayList(FORECAST_KEY);
adapter.setModel(items);
}else {
if(isOnline()) {
weekWeatherData();
}else{
Toast.makeText(getActivity(),"No internet connection",Toast.LENGTH_SHORT).show();
}
}
return rootView;
}
private void weekWeatherData() {
modelList.clear();
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.GET,
BASE_URL,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("TAG", response.toString());
try {
m = new Model();
JSONObject cityObject = response.getJSONObject("city");
String city = cityObject.getString("name");
String country = cityObject.getString("country");
JSONArray jsonObject = response.getJSONArray("list");
for(int i = 0;i<jsonObject.length();i++){
m = new Model();
m.setCity(city);
m.setCountry(country);
//list:
// {"dt":1464343200,"temp":{"day":23.05,"min":8.65,"max":24.96,"night":13.22,"eve":24.85,"morn":8.65},
// "pressure":950.2,"humidity":41,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"
// }],
// "speed":1.16,"deg":342,"clouds":0}
JSONObject innerJSON = jsonObject.getJSONObject(i);
long dateTime = innerJSON.getLong("dt");
Date weekDay = new Date(dateTime * 1000L);
SimpleDateFormat outFormat = new SimpleDateFormat("EEEE");
String day = outFormat.format(weekDay);
SimpleDateFormat outFormat1 = new SimpleDateFormat("dd MMM");
String date = outFormat1.format(weekDay);
m.setDay(day);
m.setDate(date);
m.setDay(day);
//temp:{"day":26.92,"min":19.48,"max":26.92,"night":19.48,"eve":25.65,"morn":26.92}
JSONObject tempObject = innerJSON.getJSONObject("temp");
m.setTemperature(tempObject.getString("day"));
m.setMaxTemperature(tempObject.getString("max"));
m.setMinTemperature(tempObject.getString("min"));
double pressure = innerJSON.getDouble("pressure");
int humidity = innerJSON.getInt("humidity");
m.setPressure(String.valueOf(pressure));
m.setHumidity(String.valueOf(humidity));
JSONArray weather = innerJSON.getJSONArray("weather");
for(int j=0;j<weather.length();j++){
JSONObject weatherObject = weather.getJSONObject(j);
m.setDescription(weatherObject.getString("description"));
m.setImageIcon(IMG_URL+weatherObject.getString("icon"));
}
double speed = innerJSON.getDouble("speed");
m.setSpeed(String.valueOf(speed));
modelList.add(m);
}
} catch (JSONException e) {
Log.e("TAG", e.toString());
}
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
// Adding request to request queue
AppController.getInstance().addToRequestQueue(jsonObjReq);
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.v("Theo","onSaveInstanceState called");
outState.putParcelableArrayList(FORECAST_KEY,modelList);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.v("Theo","onDestroy called");
}
protected boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnectedOrConnecting()) {
return true;
} else {
return false;
}
}
}
Change:
ft.replace(R.id.main_content, forecastFragment, "forecastfragment");
To:
ft.replace(R.id.main_content, forecastFragment, tag);
Because your tag (i.e. "forecastFragment") string value is different than the tag you are passing while adding the fragment (i.e. "forecastfragment"). That's why it is not able to find the fragment by tag and adding it everytime on clicking.
I found another solution too.
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.forecast) {
ForecastFragment forecastFragment = null;
int backStackEntryCount =
getSupportFragmentManager().getBackStackEntryCount();
if (backStackEntryCount == 0 && forecastFragment == null) {
forecastFragment = new ForecastFragment();
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.main_content, forecastFragment);
ft.addToBackStack("added today current");
forecastFragment.setArguments(b);
//fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
ft.commit();
}else{
//getSupportFragmentManager().findFragmentById(R.id.main_content);
}
}
return super.onOptionsItemSelected(item);
}
Related
I post API in HomePageActivity and get the Data, and I use the parameters to pass the data to NewFragment and show it.
Now, what I want is that when the user in NewFragment uses the swiperefresh, NewFragment will call the function in HomePageActivty, and the function will clean the data and recall the post API to get the new data and write into the parameters to send to NewFragment, then NewFragment will reload the new data and show it.
I can call the function in HomePageActivty and recall the post API, but when I want to reload the data to NewFragment, it can't show it!
How can I fix this issue?
Here is my HomePageActivity:
public class HomePageActivity extends AppCompatActivity {
public static String TAG = "HomePageActivity";
private postSectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
public static String[] HomeToNew_user_icon, HomeToNew_user_name, HomeToNew_post_time, HomeToNew_post_text, HomeToNew_post_img, HomeToNew_post_likes, HomeToNew_post_comments, HomeToNew_post_pid = null;
public static int NewArrayLength;
private static String token;
public static Context context;
#SuppressLint("ResourceType")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_page);
context = HomePageActivity.this;
mSectionsPagerAdapter = new postSectionsPagerAdapter(getSupportFragmentManager());
mViewPager = findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
token = MainActivity.memoryToken;
Toast.makeText(this,"Token in HomePage: " + token, Toast.LENGTH_SHORT).show();
new JSONTask_New(HomePageActivity.this, token, "0", block).execute("api");
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
tabLayout.getTabAt(0).setText(R.string.New_Tab);
tabLayout.getTabAt(1).setText(R.string.Hot_Tab);
}
public static void refresh_New_Data(){
initData();
reLoad();
}
public static void initData(){
HomeToNew_user_icon = null;
HomeToNew_user_name = null;
HomeToNew_post_time = null;
HomeToNew_post_text = null;
HomeToNew_post_img = null;
HomeToNew_post_likes = null;
HomeToNew_post_comments = null;
HomeToNew_post_pid = null;
NewArrayLength = 0;
}
public static void reLoad(){
new JSONTask_New(context, token, "0", "1").execute("http://52.69.75.199/cp/posts/");
Log.e(TAG, "REFRESH New(HomePage) ApiCall posts!");
}
public class postSectionsPagerAdapter extends FragmentPagerAdapter {
public postSectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 2;
}
#Override
public Fragment getItem(int position) {
switch (position){
case 0:
return new NewFragment();
case 1:
return new HotFragment();
}
return null;
}
}
// Post New (GET).
public static class JSONTask_New extends AsyncTask<String, String, String> {
private Context context;
private String token;
private String type;
private String block;
public JSONTask_New(Context context, String token, String type, String block) {
this.context = context;
this.token = token;
this.type = type;
this.block = block;
}
#Override
protected String doInBackground(String... params) {
try {
String SERVER_WS_URL = params[0];
LinkedHashMap<String, String> parameter = new LinkedHashMap<>();
parameter.put("token", token);
parameter.put("type", "0");
parameter.put("block", "0");
return ApiCall.getWebserviceCall(SERVER_WS_URL, parameter);
} catch (Exception e) {
return null;
}
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
try {
if (result != null) {
JSONObject jsonObject = new JSONObject(result.toString());
String code = jsonObject.getString("code");
String desc = jsonObject.getString("desc");
if (Integer.valueOf(code) == 1) {
JSONArray jsonArray = jsonObject.getJSONArray("list");
HomeToNew_user_icon = new String[jsonArray.length()];
HomeToNew_user_name = new String[jsonArray.length()];
HomeToNew_post_time = new String[jsonArray.length()];
HomeToNew_post_text = new String[jsonArray.length()];
HomeToNew_post_img = new String[jsonArray.length()];
HomeToNew_post_likes = new String[jsonArray.length()];
HomeToNew_post_pid = new String[jsonArray.length()];
HomeToNew_post_comments = new String[jsonArray.length()];
NewArrayLength = jsonArray.length();
for(int i = 0; i < jsonArray.length(); i++){
JSONObject jsonObject_item = jsonArray.getJSONObject(i);
HomeToNew_user_icon[i] = jsonObject_item.getString("head");
HomeToNew_user_name[i] = jsonObject_item.getString("name");
HomeToNew_post_time[i] = jsonObject_item.getString("created");
HomeToNew_post_text[i] = jsonObject_item.getString("txt");
HomeToNew_post_img[i] = jsonObject_item.getString("img");
HomeToNew_post_likes[i] = jsonObject_item.getString("gd");
HomeToNew_post_comments[i] = jsonObject_item.getString("co");
HomeToNew_post_pid[i] = jsonObject_item.getString("pid");
}
} else {
Toast.makeText(context, "NewPost API code: " + code + ", desc: " + desc, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(context, "NewPost data null!", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
}
Here is my NewFragment:
public class NewFragment extends Fragment {
public static String TAG = "NewFragment";
private RecyclerView postcardRecycler;
private ArrayList<PostCard> post_data = new ArrayList<>();
private PostCardImageAdapter adapter;
private String[] user_icon, user_name, post_time, post_text, post_img, post_likes, post_comments, post_pid = null;
private SwipeRefreshLayout swipeRefreshLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.new_layout, container, false);
user_icon = HomePageActivity.HomeToNew_user_icon;
user_name = HomePageActivity.HomeToNew_user_name;
post_time = HomePageActivity.HomeToNew_post_time;
post_text = HomePageActivity.HomeToNew_post_text;
post_img = HomePageActivity.HomeToNew_post_img;
post_likes = HomePageActivity.HomeToNew_post_likes;
post_comments = HomePageActivity.HomeToNew_post_comments;
post_pid = HomePageActivity.HomeToNew_post_pid;
postcardRecycler = view.findViewById(R.id.new_layout_recycler);
for(int i = 0; i < HomePageActivity.NewArrayLength; i++){
post_data.add(new PostCard(user_icon[i], user_name[i], post_time[i], post_text[i], post_img[i], post_likes[i], post_comments[i], post_pid[i]));
}
final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
postcardRecycler.setLayoutManager(layoutManager);
adapter = new PostCardImageAdapter(getActivity(), post_data);
postcardRecycler.setAdapter(adapter);
swipeRefreshLayout = view.findViewById(R.id.new_layout_swipe_refresh);
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#SuppressLint("ResourceType")
#Override
public void onRefresh() {
Log.e(TAG, "Enter New onRefresh!");
HomePageActivity.refresh_New_Data();
NewFragment fragment = new NewFragment();
getFragmentManager().beginTransaction().replace(R.id.container, fragment).commit();
swipeRefreshLayout.setRefreshing(false);
}
});
return view;
}
}
Here is my new_layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/new_layout_swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/new_layout_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
</android.support.v4.widget.SwipeRefreshLayout>
Any help would be highly appreciated.
method FragmentTransaction#replace require a containerViewId but not layoutId
https://developer.android.com/reference/android/support/v4/app/FragmentTransaction.html#replace_1
so that, when you call replace(R.layout.new_layout, fragment) will throw an exception
Solution: You can store newFragment in HomePageActivity and add method inflateData in NewFragment. When fetch data success, will call newFragment.inflateData()
So many people have faced this exception and i tried the solutions available for this exception but none of it actually worked for my case.
So my problem is i have a filter button at my toolbar and it has three items in it 1. ascending order , 2. descending order , 3. date specific. when i am selecting ascending and descending items data is getting populated correctly inside recyclerview. but when i am selecting the date specific option and showing a datepicker ....the data is not getting populated inside recyclerview and when i touch screen application gets crashed and gives me the above mentioned exception.
my code for fragment where i am performing these operations :-
public class PendingOrders extends Fragment {
String filterString="date_desc";
String filterDateString="";
private int mDay,mMonth,mYear;
private static final String TAG = "PendingORDERS";
private RecyclerView mMessagesView;
private List<PendingOrderModel> mMessages = new ArrayList<PendingOrderModel>();
CustomItemClickListener listener;
private PendingOrderAdapter mAdapter;
private Socket mSocket;
private Boolean isConnected = true;
public static final int DIALOG_FRAGMENT = 1;
String actualPrice,amount,total,filledAmount,orderPrice,proceeds,orderDate,orderType,orderId;
String currencyname,order,order1,orderType1 , orderDate1,idz;
public PendingOrders() {
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mAdapter = new PendingOrderAdapter(context, mMessages,listener);
if (context instanceof Activity) {
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
AppController app = (AppController) getActivity().getApplication();
SharedPreferences pref = getActivity().getSharedPreferences("MyPREFERENCES", 0);
idz=pref.getString("ZuserID", null);
mSocket = app.getSocket();
mSocket.on("pending_orders_data", orderCompletedData);
mSocket.connect();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_pending_orders, container, false);
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMessagesView = (RecyclerView) view.findViewById(R.id.rv_pending_orders);
mMessagesView.setLayoutManager(new LinearLayoutManager(getActivity()));
mMessagesView.setItemAnimator(null);
mAdapter = new PendingOrderAdapter(getActivity(), mMessages, new CustomItemClickListener() {
#Override
public void onItemClick(View v, int position) {
String orderid = mMessages.get(position).getmOrderId();
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
Fragment prev = getActivity().getSupportFragmentManager().findFragmentByTag("dialog");
if (prev != null) {
ft.remove(prev);
}
ft.addToBackStack(null);
DialogFragment dialogFrag = PendingCancelDialog.newInstance(123);
dialogFrag.show(getActivity().getFragmentManager().beginTransaction(), "dialog");
Bundle args = new Bundle();
args.putString("ID",orderid);
dialogFrag.setArguments(args);
}
});
mMessagesView.setAdapter(mAdapter);
initObjects();
}
private void initObjects() {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("user_id", idz);
} catch (JSONException e) {
e.printStackTrace();
}
mSocket.emit("register_user", jsonObject.toString());
mSocket.emit("fetch_pending_orders", getSendMessageString(""));
}
public String getSendMessageString(String message) {
try {
JSONObject jsonObject = new JSONObject();
jsonObject.put("page_no", "1"); //1: text message 2: multimedia message
jsonObject.put("user_id", idz);
jsonObject.put("records_per_page", "5");
jsonObject.put("filter", filterString);
Log.i("??", "filterString: "+filterString);
jsonObject.put("filter_date", filterDateString);
Log.i("??", "filterDateString: "+filterDateString);
return jsonObject.toString();
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
private void addMessage(String orderId,String order,String currencyname,String amount,String filledAmount,String proceeds,String orderPrice,String orderDate,String orderType) {
mMessages.add(new PendingOrderModel.Builder(PendingOrderModel.RECEIVER)
.orderid(orderId).order(order).amount(amount).currencyname(currencyname).filledamount(filledAmount).orderprice(orderPrice).proceeds(proceeds).orderdate(orderDate).ordertype(orderType).build());
mMessagesView.getRecycledViewPool().clear();
mAdapter.notifyDataSetChanged();
}
private Emitter.Listener orderCompletedData = new Emitter.Listener() {
#Override
public void call(final Object... args) {
if(getActivity() != null) {
getActivity().runOnUiThread(() -> {
JSONArray object1 = (JSONArray) args[0];
if(object1 != null){
JSONArray array = new JSONArray();
array = object1.optJSONArray(0);
int arraylength = array.length();
for(int j=0; j<array.length();j++){
JSONObject obj = new JSONObject();
try {
obj = array.getJSONObject(j);
currencyname = obj.getString("coin");
orderId = obj.getString("id");
order1 = obj.getString("order");
filledAmount = obj.getString("coin_quantity");
amount = obj.getString("total_amount");
proceeds = obj.getString("remaining");
orderPrice = obj.getString("order_price");
orderDate1 = obj.getString("create_time");
orderType1= obj.getString("order_type");
} catch (JSONException e) {
e.printStackTrace();
}
if(order1 == "1"){
order = "Limit";
}
else{
order = "Market";
}
if(orderType1 == "1"){
orderType = "Sell";
}else{
orderType = "buy";
}
String [] date = orderDate1.split("T");
orderDate = date[0].trim();
addMessage(orderId,order,currencyname,amount,filledAmount,proceeds,orderPrice,orderDate,orderType);
}
}
});
}
}
};
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.asc_order:
filterString="date asc";
filterDateString="";
mMessages.clear();
mSocket.emit("fetch_pending_orders", getSendMessageString(""));
return true;
case R.id.desc_order:
filterString="date desc";
mMessages.clear();
mSocket.emit("fetch_pending_orders", getSendMessageString(""));
return true;
case R.id.pick_date:
filterString="date specific";
mMessages.clear();
pickdate();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void pickdate() {
Calendar c1 = Calendar.getInstance();
mYear = c1.get(Calendar.YEAR);
mMonth = c1.get(Calendar.MONTH);
mDay = c1.get(Calendar.DAY_OF_MONTH);
DatePickerDialog datePickerDialog = new DatePickerDialog(getActivity(),R.style.DAte_Theme,
(view, year, monthOfYear, dayOfMonth) -> {
int month = monthOfYear + 1;
String formattedMonth = "" + month;
String formattedDayOfMonth = "" + dayOfMonth;
if(month < 10){
formattedMonth = "0" + month;
}
if(dayOfMonth < 10){
formattedDayOfMonth = "0" + dayOfMonth;
}
filterDateString= formattedDayOfMonth + "/" + formattedMonth + "/" + year;
Log.i("date",filterDateString);
mSocket.emit("fetch_pending_orders", getSendMessageString(""));
// updateDate(filterDateString);
}, mYear, mMonth, mDay);
datePickerDialog.show();
}
}
Below is my Logcat :-
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{cfdb59c position=3 id=-1, oldPos=-1, pLpos:-1 no parent} android.support.v7.widget.RecyclerView{476168c VFED..... .F...... 0,0-1080,1560 #7f090169 app:id/rv_pending_orders}, adapter:com.vamediabox.greenpay.adapters.PendingOrderAdapter#d6e71d5, layout:android.support.v7.widget.LinearLayoutManager#e738dea, context:com.vamediabox.greenpay.activities.MyorderActivity#70a64f9
at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5421)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5603)
at android.support.v7.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:285)
at android.support.v7.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:342)
at android.support.v7.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:358)
at android.support.v7.widget.GapWorker.prefetch(GapWorker.java:365)
at android.support.v7.widget.GapWorker.run(GapWorker.java:396)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
See just do one thing when you select the date picker then add these lines before calling the main function.
onClick
{
adapter.notifyDataSetChanged();
recyclerView.getRecycledViewPool().clear();
and then the rest code....
}
i want to transfer data from activity to fragment, it always prints this error. i tried to use different techniques to overcome this like intent but still stuck. do i miss something in my code in activity or in the fragment ?
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.junaida.project1, PID: 14447
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.junaida.project1/com.example.junaida.project1.Year}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2957)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3018)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1653)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6724)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
at com.example.junaida.project1.fragments.CardFragment.onCreateView(CardFragment.java:89)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2354)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1419)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:799)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2580)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2367)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2322)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2229)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3221)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3171)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:192)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:560)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:177)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1256)
at android.app.Activity.performStart(Activity.java:6959)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2920)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3018)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1653)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6724)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
this error points to
String id = bundle.getString("id");
i will list the class where i transfer data from
public class Year extends AppCompatActivity {
ImageView back;
GridView grid;
String id;
String type;
String year;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_year);
Intent data = getIntent();
year = data.getStringExtra("year");
id = data.getStringExtra("id");
type = data.getStringExtra("type");
BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
//show the original color of icons
bottomNavigationView.setItemIconTintList(null);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
final Bundle bundle = new Bundle() ;
Intent intent;
switch (item.getItemId()) {
case R.id.action_item1:
bundle.putString("year",year);
bundle.putString("id",id);
bundle.putString("type",type);
//selectedFragment.setArguments(bundle);
selectedFragment = new CardFragment();
selectedFragment.setArguments(bundle);
break;
case R.id.action_item2:
bundle.putString("year",year);
bundle.putString("id",id);
bundle.putString("type",type);
//selectedFragment.setArguments(bundle);
selectedFragment = new AudioFragment();
selectedFragment.setArguments(bundle);
break;
case R.id.action_item3:
bundle.putString("year",year);
bundle.putString("id",id);
bundle.putString("type",type);
//selectedFragment.setArguments(bundle);
selectedFragment = new VideoFragment();
selectedFragment.setArguments(bundle);
break;
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.content_frame2, selectedFragment);
transaction.commit();
return true;
}
});
//Manually displaying the first fragment - one time only
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.content_frame2, new CardFragment());
transaction.commit();
back = (ImageView)findViewById(R.id.back_year);
back.setOnClickListener(new AdapterView.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
}
});
}
}
my fragment is
public class CardFragment extends Fragment {
// String id;
// String type;
// String year;
private ListAdapter adapter;
TextView textView;
private ListView lv;
private List<ListItemsData> list = new ArrayList<ListItemsData>();
private static final String url = "http://10.94.0.204/WebApplication7/api/subjects";
public CardFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle bundle = this.getArguments();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_card, container, false);
//final ArrayList<ListItemsData> listItem = GetlistItems();
Bundle bundle = this.getArguments();
String id = bundle.getString("id");
String year = bundle.getString("year");
String type = bundle.getString("type");
final Activity mActivity = this.getActivity();
// lv.setAdapter(new ListAdapter(getActivity(), listItem));
adapter = new ListAdapter(getContext(), list);
lv.setAdapter(adapter);
try {
RequestQueue requestQueue = Volley.newRequestQueue(getContext());
String URL = "http://10.94.0.204/WebApplication7/api/subjects";
JSONObject jsonBody = new JSONObject();
// jsonBody.put("tblRegisteredUsers_nickName", username.getText().toString().trim());
jsonBody.put("id", id.toString());
jsonBody.put("Type", type.toString());
jsonBody.put("Year", year.toString());
final String requestBody = jsonBody.toString();
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
if (response.equals("success")) {
//login authenticated. Start the next activity of your app
Toast.makeText(getActivity(), response.toString(), Toast.LENGTH_LONG).show();
// Toast.makeText(getApplicationContext(), "registered successfully ", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(getActivity(), MainActivity.class);
// intent.putExtra("id", Id);
// intent.putExtra("year", year);
startActivity(intent);
} else {
//login failed. prompt to re-enter the credentials
Toast.makeText(mActivity.getApplicationContext(), "Failed to log In", Toast.LENGTH_SHORT).show();
Log.i("VOLLEY", response);
Toast.makeText(mActivity.getApplicationContext(), response.toString(), Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", error.toString());
}
})
{
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "utf-8");
return null;
}
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String responseString;
String json = null;
try {
json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
responseString = String.valueOf(json).trim();
ArrayList<Response4> list_response = new ArrayList<Response4>();
Type listType = new TypeToken<List<Response4>>() {
}.getType();
list_response = new Gson().fromJson(responseString, listType);
//String check = list.get(0).getMessagesName();
for (int i = 0; i < list_response.size(); i++) {
// JSONObject obj = response.getJSONObject(i);
ListItemsData listItemData = new ListItemsData();
listItemData.setItem(list_response.get(i).getMessagesName());
listItemData.setUrl(list_response.get(i).getMessageURLNew());
//listItemData.setUrl((obj.getString("url")));
list.add(listItemData);
//Id = list.get(0).getId();
// year = list.get(0).getYear();
//Response2 yourModel = new Gson().fromJson(responseString, Response2.class);
}
// i should have this peice of code for methods that are in the background
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
adapter.notifyDataSetChanged();
}
});
// String Check = yourModel.getMessagetitle();
return Response.success(list_response.toString(), HttpHeaderParser.parseCacheHeaders(response));
}
};
requestQueue.add(stringRequest);
} catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return rootView;
}
am i sending the data in correct way ?
any help would be appreciated
You should be using getArguments() when getting the bundle from the fragment.
get the bundle like this
public View onCreateView(LayoutInflater inflater, ViewGroup containerObject,Bundle savedInstanceState){
//here is your arguments
Bundle bundle=getArguments();
//get string like this
String year = bundle.getString("year");
}
edit : make a function like this and add to your default fragment as well as other fragment starting from navigation menu.
private Bundle getBundle(Intent data){
Bundle bundle = new Bundle();
bundle.putString("year",data.getStringExtra("year"));
bundle.putString("id",data.getStringExtra("id"));
bundle.putString("type",data.getStringExtra("type"));
}
here is final code
public class Year extends AppCompatActivity {
ImageView back;
GridView grid;
String id;
String type;
String year;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_year);
Intent data = getIntent();
//get a bundle set and ready to use anytime
Bundle myBundle= getBundle(data);
BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
//show the original color of icons
bottomNavigationView.setItemIconTintList(null);
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()) {
case R.id.action_item1:
selectedFragment = new CardFragment();
selectedFragment.setArguments(myBundle);
break;
case R.id.action_item2:
selectedFragment = new AudioFragment();
selectedFragment.setArguments(myBundle);
break;
case R.id.action_item3:
selectedFragment = new VideoFragment();
selectedFragment.setArguments(myBundle);
break;
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.content_frame2, selectedFragment);
transaction.commit();
return true;
}
});
//Manually displaying the first fragment - one time only
CardFragment myCardFragment = new CardFragment();
myCardFragment.setArguments(myBundle);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.content_frame2, myCardFragment);
transaction.commit();
back = (ImageView)findViewById(R.id.back_year);
back.setOnClickListener(new AdapterView.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
}
});
}
private Bundle getBundle(Intent data){
Bundle bundle = new Bundle();
bundle.putString("year",data.getStringExtra("year"));
bundle.putString("id",data.getStringExtra("id"));
bundle.putString("type",data.getStringExtra("type"));
}
}
I m working on a project in which i have to add the tabs and the data dynamically from the json.
The following is the code in the activity in which i add the tabs
private void getShopDetails() {
coordinatorLayout.setVisibility(View.GONE);
new ProgressDialog(this);
ProgressDialog.show();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(shopDetailsJsonUrl, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
SharedPreferences sharedPreferences = getSharedPreferences("ShopDetailsJson", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("sdresponse", response.toString());
editor.apply();
ProgressDialog.dismiss();
coordinatorLayout.setVisibility(View.VISIBLE);
try {
JSONArray shopDetailsArray = response.getJSONArray("shop_details");
JSONObject shopDetailsObj = shopDetailsArray.getJSONObject(0);
shopName = shopDetailsObj.getString("shop_name");
phone = shopDetailsObj.getString("tel");
shopNum = shopDetailsObj.getString("shop_no");
shopAddress = shopDetailsObj.getString("shop_address");
shopImage = shopDetailsObj.getString("featured_image");
Glide.with(getApplicationContext()).load("http://allmartapp.com/appapi/uploads/" + shopImage).diskCacheStrategy(DiskCacheStrategy.SOURCE).into(backdrop);
colLayout.setTitle(shopName);
address.setText("Address - " + shopAddress);
JSONArray tabsArray = response.getJSONArray("category");
if (tabsArray != null) {
categoryId = new int[tabsArray.length()];
for (int i = 0; i < tabsArray.length(); i++) {
JSONObject tabsObj = tabsArray.getJSONObject(i);
tabLayout.addTab(tabLayout.newTab().setText(tabsObj.getString("category_name")));
categoryId[i] = tabsObj.getInt("category_id");
}
tabLayout.setTabGravity(TabLayout.GRAVITY_CENTER);
PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager(), tabLayout.getTabCount());
pager.setAdapter(pagerAdapter);
pager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
pager.setOffscreenPageLimit(tabLayout.getTabCount());
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
pager.setCurrentItem(tab.getPosition());
ShopDetailsTabsFragment.sgetid(categoryId[tab.getPosition()]);
Log.d("CATIID", categoryId[tab.getPosition()] + "");
pager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
ProgressDialog.dismissWithError();
}
});
int socketTimeout = 30000;//30 seconds - change to what you want
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
jsonObjectRequest.setRetryPolicy(policy);
AppController.getInstance().addToRequestQueue(jsonObjectRequest);
}
Following is the code of fragment
public class ShopDetailsTabsFragment extends Fragment {
RecyclerView recyclerView;
boolean isViewShown = true;
CategoryListItemsAdapter shopListRvAdapters;
private String shopDetailsJsonUrl = "http://allmartapp.com/appapi/json/get_shop_details_by_shop_id/";
private String baseshopDetailsJsonUrl = "http://allmartapp.com/appapi/json/get_shop_details_by_shop_id/";
ArrayList<CategoryItemsListModel> arrayList = new ArrayList<>();
static int catid = 0;
int shopId;
Boolean isdataloaded = false;
ProgressBar progressBar;
private boolean fragmentResume = false;
private boolean fragmentVisible = true;
private boolean fragmentOnCreated = false;
public ShopDetailsTabsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_shop_details_tabs, container, false);
recyclerView = (RecyclerView) v.findViewById(R.id.rv);
recyclerView.setLayoutManager(new GridLayoutManager(getActivity(), 2));
progressBar = (ProgressBar) v.findViewById(R.id.progressBarTabs);
SharedPreferences sharedPreferences = getActivity().getSharedPreferences("SHOPID", Context.MODE_PRIVATE);
shopId = sharedPreferences.getInt("shopid", 0);
if (!fragmentResume && fragmentVisible) { //only when first time fragment is created
makeJsonRequest();
}
shopListRvAdapters = new CategoryListItemsAdapter(arrayList, getActivity());
recyclerView.setAdapter(shopListRvAdapters);
return v;
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser && isResumed()) { // only at fragment screen is resumed
fragmentResume = true;
fragmentVisible = false;
fragmentOnCreated = true;
makeJsonRequest();
} else if (isVisibleToUser) { // only at fragment onCreated
fragmentResume = false;
fragmentVisible = true;
fragmentOnCreated = true;
} else if (!isVisibleToUser && fragmentOnCreated) {// only when you go out of fragment screen
fragmentVisible = false;
fragmentResume = false;
}
// if (getView() != null) {
// isViewShown = true;
// makeJsonRequest();
//
//
// // fetchdata() contains logic to show data when page is selected mostly asynctask to fill the data
// } else {
// isViewShown = false;
// }
}
public static void sgetid(int cat) {
catid = cat;
}
private void getShopCat() {
recyclerView.setAdapter(null);
shopDetailsJsonUrl += shopId;
arrayList.clear();
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(shopDetailsJsonUrl, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
isdataloaded = true;
Log.d("JSON", response.toString());
try {
JSONArray categoryArray = response.getJSONArray("category");
if (arrayList != null) {
if (arrayList.size() > 0)
arrayList.clear();
}
for (int i = 0; i < categoryArray.length(); i++) {
JSONObject catObj = categoryArray.getJSONObject(i);
int category_id = catObj.getInt("category_id");
if (category_id == catid) {
JSONArray productArray = catObj.getJSONArray("product");
for (int j = 0; j < productArray.length(); j++) {
JSONObject productObj = productArray.getJSONObject(j);
String name = productObj.getString("product_name");
String image = "http://allmartapp.com/appapi/uploads/" + productObj.getString("image_name");
int id = productObj.getInt("product_id");
int price = productObj.getInt("price");
arrayList.add(new CategoryItemsListModel(id, image, name, price));
}
shopListRvAdapters = new CategoryListItemsAdapter(arrayList, getActivity());
recyclerView.setAdapter(shopListRvAdapters);
shopListRvAdapters.notifyDataSetChanged();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
int socketTimeout = 30000;//30 seconds - change to what you want
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
jsonObjectRequest.setRetryPolicy(policy);
AppController.getInstance().addToRequestQueue(jsonObjectRequest);
shopDetailsJsonUrl = baseshopDetailsJsonUrl;
}
void makeJsonRequest() {
SharedPreferences sharedPreferences = getActivity().getSharedPreferences("ShopDetailsJson", Context.MODE_PRIVATE);
String response = sharedPreferences.getString("sdresponse", null);
try {
JSONArray jsonArray = new JSONObject(response).getJSONArray("category");
Log.d("TBASARRAY", jsonArray + "");
progressBar.setVisibility(View.GONE);
if (arrayList != null) {
if (arrayList.size() > 0)
arrayList.clear();
}
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject catObj = jsonArray.getJSONObject(i);
int category_id = catObj.getInt("category_id");
if (category_id == catid) {
JSONArray productArray = catObj.getJSONArray("product");
for (int j = 0; j < productArray.length(); j++) {
JSONObject productObj = productArray.getJSONObject(j);
String name = productObj.getString("product_name");
String image = "http://allmartapp.com/appapi/uploads/" + productObj.getString("image_name");
int id = productObj.getInt("product_id");
int price = productObj.getInt("price");
arrayList.add(new CategoryItemsListModel(id, image, name, price));
}
shopListRvAdapters = new CategoryListItemsAdapter(arrayList, getActivity());
recyclerView.setAdapter(shopListRvAdapters);
shopListRvAdapters.notifyDataSetChanged();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
recyclerView.addOnItemTouchListener(new CategoryListActivity.RecyclerTouchListener(getActivity(), recyclerView, new CategoryListActivity.OnClickListener() {
#Override
public void onClick(View v, int position) {
int id = arrayList.get(position).getId();
SharedPreferences sharedPreferences = getActivity().getSharedPreferences("CATITEMID", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("catitemid", id);
editor.apply();
startActivity(new Intent(getActivity(), ItemDetailView.class));
}
#Override
public void onLongClick(View v, int position) {
}
}));
// shopDetailsJsonUrl = baseshopDetailsJsonUrl;
}
My problem is that the function makeJsonRequest() is only called when i swipe the tabs. Actually the onCreateview method is not called unless i swipe the tabs.
And also, when i press back and come back to that activity, the data of that tab that was left when pressing back appears at the first tab.
Any help/ guidance will be appreciated.
I would suggest you looking at theViewPager's setOffscreenPageLimit(int) method.
It controls how many tabs left/right must be preinitialised before showing them.
As for 'back' problem. Probably the first fragment is 'added' to the activity Backstack, and the other ones are 'replaced'. Therefore calling onBackPressed of Activity is just going back in the Backstack.
I'm fighting with this for a week, without luck.
From the begining:
There is an Activity with Navigation Drawer included. This activity has it's own fragments. Fragments have logic to send requests to a weather api and logic to update themselves with given data. At the first run everything seems to work fine! I'm able to send request and fill views with given data (using okHttp).
Everything is starting to collapse after fragments recreations, I'm getting constantly getActivity() to be null ;(
Code Sample below:
Fragments first initialisation:
public abstract class DoubleFragmentActivity extends AppCompatActivity {
protected static final String TOP_FRAGMENT = "TOP_FRAGMENT";
protected static final String BOTTOM_FRAGMENT = "BOTTOM_FRAGMENT";
protected abstract Fragment topFragment();
protected abstract Fragment bottomFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_container);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.topFragmentContainer, topFragment(), TOP_FRAGMENT)
.add(R.id.bottomFragmentContainer, bottomFragment(), BOTTOM_FRAGMENT)
.commit();
getSupportFragmentManager().executePendingTransactions();
}
}
}
Navigation Drawer:
private void selectDrawerItem(MenuItem menuItem) {
Fragment f;
Fragment f2;
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
switch (menuItem.getItemId()) {
case R.id.forecastFragment:
f = getSupportFragmentManager().findFragmentByTag("TOP_FRAGMENT");
f2 = getSupportFragmentManager().findFragmentByTag("BOTTOM_FRAGMENT");
if (f != mCurrentForecastFragment || f2 != mDailyForecastFragment) {
ft.replace(R.id.topFragmentContainer, new CurrentForecastFragment(), "TOP_FRAGMENT");
ft.replace(R.id.bottomFragmentContainer, new DailyForecastFragment(), "BOTTOM_FRAGMENT");
} else {
}
break;
case R.id.settingsFragment:
mToolbar.setVisibility(View.INVISIBLE);
f = new SettingsFragment();
ft.replace(R.id.topFragmentContainer, f);
break;
case R.id.paymentsFragment:
f = new PaymentsFragment();
ft.replace(R.id.topFragmentContainer, f);
break;
case R.id.aboutFragment:
break;
default:
}
getSupportFragmentManager().executePendingTransactions();
ft.commit();
menuItem.setChecked(true);
setTitle(menuItem.getTitle());
mDrawer.closeDrawers();
}
Fragment`s logic for connecting and fullfilling data:
public void makeConnectionToApi(String lat, String lon) {
mWeatherParams.setLanguage(Locale.getDefault().getLanguage());
Activity a = getActivity();
Uri.Builder currentBuilder = new Uri.Builder();
currentBuilder.scheme("http")
.authority("api.openweathermap.org")
.appendPath("data")
.appendPath("2.5")
.appendPath("weather")
.appendQueryParameter(WeatherConstants.KEY_LATITUDE, lat)
.appendQueryParameter(WeatherConstants.KEY_LONGITUDE, lon)
.appendQueryParameter(WeatherConstants.KEY_UNITS, mUnit)
.appendQueryParameter(WeatherConstants.KEY_LANGUAGE, mWeatherParams.getLanguage())
.appendQueryParameter("APPID", "###");
String currentUrl = currentBuilder.build().toString();
if (mUtility.isNetworkAvalaible()) {
Request requestCurrent = new Request.Builder().url(currentUrl).build();
//FIRST CALL
mCall = client.newCall(requestCurrent);
mCall.enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Bundle args = new Bundle();
args.putString(TAG, e.toString());
Utility.invokeDialog(TAG, e.toString(), getFragmentManager());
}
#Override
public void onResponse(Response response) throws IOException {
String responseBody = String.valueOf(response.body().string());
try {
mForecast.setCurrent(fetchCurrent(responseBody));
} catch (JSONException e) {
e.printStackTrace();
}
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
fillViewWithValues();
}
});
}
});
} else {
Utility.invokeDialog(TAG, "Check your internet connection!", getFragmentManager());
}
}
private Current fetchCurrent(String responseBody) throws JSONException {
Current current = new Current();
JSONObject jo = new JSONObject(responseBody);
//FETCH WEATHER ARRAY
JSONArray weather = jo.getJSONArray(WeatherConstants.KEY_CURRENT_CONDITIONS_ARRAY);
for (int j = 0; j < weather.length(); j++) {
JSONObject weatherParser = weather.getJSONObject(j);
current.setIcon(weatherParser.getString(WeatherConstants.KEY_ICON_ID));
Log.i(TAG, "Icons ID: " + weatherParser.getString(WeatherConstants.KEY_ICON_ID));
current.setConditions(weatherParser.getString(WeatherConstants.KEY_DESCRIPTION));
}
//FETCH TEMP
JSONObject temp = jo.getJSONObject(WeatherConstants.KEY_MAIN_OBJECT);
current.setDay(temp.getDouble(WeatherConstants.KEY_TEMP));
current.setPressure(temp.getDouble(WeatherConstants.KEY_PRESSURE));
current.setHumidity(temp.getDouble(WeatherConstants.KEY_HUMIDITY));
current.setDayMax(temp.getDouble(WeatherConstants.KEY_TEMP_DAY_MAX));
// FETCH VISIBILITY
if (jo.has(WeatherConstants.KEY_VISIBILITY)) {
current.setVisibility(jo.getInt(WeatherConstants.KEY_VISIBILITY));
}
//FETCH WIND
JSONObject wind = jo.getJSONObject(WeatherConstants.KEY_WIND_OBJECT);
current.setWindSpeed(wind.getDouble(WeatherConstants.KEY_WIND_SPEED));
if (wind.has(WeatherConstants.KEY_WIND_DEGREES)) {
current.setWindDegrees(wind.getInt(WeatherConstants.KEY_WIND_DEGREES));
}
JSONObject clouds = jo.getJSONObject(WeatherConstants.KEY_CLOUDS);
current.setClouds(clouds.getInt("all"));
current.setTimeStamp(jo.getInt(WeatherConstants.KEY_TIMESTAMP));
current.setCurrentLocation(jo.getString(WeatherConstants.KEY_CITY_NAME));
return current;
}
private void fillViewWithValues() {
Current current = mForecast.getCurrent();
if (mDeegreSwitch == 0) {
mCurrentTemperature.setText(current.getDay() + "\u00B0");
// setBackgroundColor(current.getDay());
} else {
int c = current.getDay();
double f = (9.0 / 5.0) * c + 32;
int e = (int) Math.round(f);
mCurrentTemperature.setText(String.valueOf((int) Math.round(f)) + "\u00B0");
// setBackgroundColor(e);
}
mCurrentCondition.setText(current.getConditions());
mPressure.setText(String.valueOf(current.getPressure()) + "hPa");
mClouds.setText(String.valueOf(current.getClouds()) + "%");
mHumidity.setText(String.valueOf(current.getHumidity()) + "%");
mCurrentIcon.setImageResource(current.getIcon());
}
Problems occurs here: getActivity().runOnUiThread inside makeConnectionToApi method. I've tried to fetch an activity from onAttach method and pass it makeConnectionToApi as parameter, it worked...but partially. App didn't crash but fragment`s view was not updated, like there was a second fragment underneath or something.
I have filling it might be something with threads or I'm doing sth wrong with fragments transaction...