Everything was running fine. But after some testing through my app it crashes and in my Logcat I see this "Content View Not Yet Created". I'm using a BaseAdapter with ListFragment.
My ListFragment Code is :
public class TaskFragment extends ListFragment {
// Adapter class for driver's task list.
private TaskListAdapter mTaskListAdapter;
// all driver trip list setter getter
private ArrayList<TaskModel> mTaskModelArrayList;
// Creating flag for view is created or not.
private boolean hasViewCreated;
private boolean mHasNewTask;
public static TaskFragment newInstance(){
return new TaskFragment();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Fix for styling list fragment :- Starts
View layout = super.onCreateView(inflater, container,
savedInstanceState);
assert layout != null;
ListView lv = (ListView) layout.findViewById(android.R.id.list);
ViewGroup parent = (ViewGroup) lv.getParent();
// Remove ListView and add CustomView in its place
int lvIndex = parent.indexOfChild(lv);
parent.removeViewAt(lvIndex);
RelativeLayout mRelativeLayout = (RelativeLayout) inflater.inflate(
R.layout.fragment_task, container, false);
parent.addView(mRelativeLayout, lvIndex, lv.getLayoutParams());
return layout;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Fix for styling list fragment ends
setHasOptionsMenu(true);
hasViewCreated = true;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mTaskModelArrayList = new ArrayList<>();
mTaskListAdapter = new TaskListAdapter(getActivity(), mTaskModelArrayList, this);
setListAdapter(mTaskListAdapter);
setListShown(false);
}
#Override
public void onResume() {
super.onResume();
loadTasks(false, false);
}
private void loadTasks(boolean showError, boolean startButtonFlag) {
// Load task from SQLite
loadTaskFromSQLiteDb();
// Check Online for new data
loadTaskFromServer(showError, startButtonFlag);
}
/**
* Fetching driver's task from mobile.
*/
private void loadTaskFromSQLiteDb() {
try {
if (mTaskModelArrayList.size() == mDBHelper.getActiveTaskCount())
return;
mTaskModelArrayList.clear();
if (mDBHelper.getActiveTaskCount() > 0) {
ArrayList<TaskModel> tasks = mDBHelper.getAllTaskView();
for (TaskModel task : tasks) {
mTaskModelArrayList.add(task);
}
setListShown(true);
}
refreshTaskList(); // notify data change
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Fetching driver's task list from server if showError value true.
* #param showError
* passing boolean value 'true'.
*/
private void loadTaskFromServer(final boolean showError, final boolean startButtonFlag) {
// if showError value true then show progress bar.
if (showError)
showProgress();
JSONObject params = new JSONObject();
JSONObject appBranchId = new JSONObject();
try {
appBranchId.put("branchId", getString(R.string.app_client_id));
params.put("myParam", appBranchId);
params.put("mobileImei", ApplicationController.getInstance()
.getDeviceInfo().get(ApplicationController.DEVICE_IMEI));
} catch (JSONException e) {
e.printStackTrace();
}
new VolleyHelper().doJsonObjectRequest(getActivity(),
VolleyHelper.POST, UrlConstants.DRIVER_TASK_LIST, params,
new VolleyResponseCallBack() {
#Override
public void onResponse(JSONObject response) {
super.onResponse(response);
try {
ApplicationController.getInstance().getRequestQueue().getCache().clear();
endProgress();
if (response.has("data")) {
switch (response.getJSONObject("data").getString("status")) {
case "success":
JSONArray employeeDetailData = response.getJSONObject("data")
.getJSONArray("empDetails");
for (int i = 0; i < employeeDetailData.length(); i++) {
TaskModel taskModel = new TaskModel();
JSONObject employeeDetailJsonObject = employeeDetailData
.getJSONObject(i);
if (!mDBHelper.isTaskExist(employeeDetailJsonObject
.getString("requestId"))) {
taskModel.setmTaskEmployeeRequestId(employeeDetailJsonObject
.getString("requestId"));
taskModel.setmTaskEmployeeId(employeeDetailJsonObject
.getString("employeeId"));
taskModel.setmTaskEmployeeName(employeeDetailJsonObject
.getString("name"));
taskModel.setmTaskEmployeeAddress(employeeDetailJsonObject
.getString("address"));
taskModel.setmTaskEmployeeShiftTime(employeeDetailJsonObject
.getString("tripTime"));
if (response.getJSONObject("data")
.getString("tripType").equalsIgnoreCase("PICKUP")) {
taskModel.setmTaskEmployeePickupTime(employeeDetailJsonObject
.getString("pickUpTime"));
taskModel.setmTaskDriverArrivedFlag(employeeDetailJsonObject
.getString("reachedFlg"));
} else if (response.getJSONObject("data")
.getString("tripType").equalsIgnoreCase("DROP")) {
taskModel.setmTaskEmployeePickupTime("No");
}
taskModel.setmTaskEmployeeLocationStatus(employeeDetailJsonObject
.getString("locationStatus"));
taskModel.setmTaskEmployeeTripType(response.getJSONObject("data")
.getString("tripType"));
taskModel.setmTaskEmployeeBoardedFlag(employeeDetailJsonObject
.getString("boardedFlg"));
if (employeeDetailJsonObject
.getString("boardedFlg").equalsIgnoreCase("N")) {
taskModel.setIsCheckBoxSelected(false);
} else {
taskModel.setIsCheckBoxSelected(true);
}
taskModel.setIsActive(true);
mHasNewTask = true;
mTaskModelArrayList.add(taskModel);
mDBHelper.addTask(taskModel);
}
}
break;
default:
break;
}
} else {
mBtnViewMap.setVisibility(Button.GONE);
}
if (mHasNewTask) {
mHasNewTask = false;
}
if (hasViewCreated)
refreshTaskList();
} catch (JSONException e) {
e.printStackTrace();
}
if (hasViewCreated)
setListShown(true);
if (showError) {
endProgress();
}
}
#Override
public void onError(VolleyError Error) {
endProgress();
}
}, true, new DialogCallBack() {
#Override
protected void onPositiveBtnClick() {
super.onPositiveBtnClick();
loadTaskFromServer(showError, startButtonFlag);
}
#Override
protected void onNegativeBtnClick() {
super.onNegativeBtnClick();
}
});
}
/**
* This method will refresh the entire task list of
* driver if something new comes from server.
*/
private void refreshTaskList() {
if (getActivity() != null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (mTaskListAdapter != null) {
mTaskListAdapter.notifyDataSetChanged();
}
}
});
}
}}
My Logcat error is :
java.lang.IllegalStateException: Content view not yet created
at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328)
at android.support.v4.app.ListFragment.setListShown(ListFragment.java:280)
at android.support.v4.app.ListFragment.setListShown(ListFragment.java:258)
at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:65)
at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5086)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Related
current I'm facing a problem which I cannot solve, I have a controller, a fragment, and an Activity, the problem is, I need the application context inside the controller, so I created an instance of the controller from the Fragment, and passed the appContext as an argument in its constructor, but an exception is thrown which is class cast exception in function getReligions() inside my controller at the line where I have a call back, any ideas how to solve this?
Here is my code
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
controller = new Controller(getActivity().getApplicationContext());
imageUploadHandler = new ImageHandler(getApplicationContext());
rootView = inflater.inflate(R.layout.setup_edit_profile, container, false);
}
public void getReligions() {
if (religions != null) {
religionSpinner();
return;
}
controller.getReligions();
}
In the controller class
public void getReligions(){
JSONObject params = new JSONObject();
RequestQueue queue = Volley.newRequestQueue(context);
String url = "https://www.doyousonder.com/api/1.0.0/religion";
queue.add(new JsonObjectRequest(com.android.volley.Request.Method.GET, url, params,
new Response.Listener<JSONObject>() {
public void onResponse(JSONObject response) {
((GeneralCallBack)context).VolleyResponse(response,"Religions");
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Authorization", orientation_adj.getContext().getResources().getString(R.string.bearer));
return params;
}
});
}
myLogCat:
java.lang.ClassCastException:
com.eseed.sonder.utils.orientation_adj cannot be cast to
com.eseed.sonder.utils.GeneralCallBack
at com.eseed.sonder.utils.Controller$61.onResponse(Controller.java:904)
at com.eseed.sonder.utils.Controller$61.onResponse(Controller.java:902)
at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:65)
at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:234)
at android.app.ActivityThread.main(ActivityThread.java:5526)
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)
Here're my callbacks
#Override
public void VolleyResponse(String data) {
}
#Override
public void VolleyResponse(JSONObject response) {
}
#Override
public void VolleyResponse(JSONObject response, String data) {
Gson gson = new Gson();
if(data.equals("Religions")){
try {
Type t = new TypeToken<ReligionData[]>() {}.getType();
religions = gson.fromJson(String.valueOf(response.getJSONObject("data").getJSONArray("list_of_religions")), t);
religion_names = new String[religions.length + 1];
religion_names[0] = "Select";
for (int i = 0; i < religions.length; i++) {
religion_names[i + 1] = (religions[i].religion_name);
}
religionSpinner();
} catch (JSONException e) {
e.printStackTrace();
}
}else if(data.equals("Nationalities")){
try {
Type t = new TypeToken<NationalityData[]>() {
}.getType();
nationalities = gson.fromJson(String.valueOf(response.getJSONObject("data").getJSONArray("list_of_nationalities")), t);
nationality_names = new String[nationalities.length + 1];
nationality_names[0] = "Select";
for (int i = 0; i < nationalities.length; i++) {
nationality_names[i + 1] = (nationalities[i].nationality_name);
}
nationalitySpinner();
loadingIcon.hide();
} catch (JSONException e) {
System.out.println(e.getMessage());
}
}
}
`public class orientation_adj extends Application {
private static Context mContext;
#Override
public void onCreate() {
super.onCreate();
Fabric.with(this, new Crashlytics());
mContext = this;
// register to be informed of activities starting up
registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
#Override
public void onActivityCreated(Activity activity,
Bundle savedInstanceState) {
// new activity created; force its orientation to portrait
activity.setRequestedOrientation(
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
#Override
public void onActivityStarted(Activity activity) {
}
#Override
public void onActivityResumed(Activity activity) {
}
#Override
public void onActivityPaused(Activity activity) {
}
#Override
public void onActivityStopped(Activity activity) {
}
#Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
#Override
public void onActivityDestroyed(Activity activity) {
}
});
}
public static Context getContext(){
return mContext;
}
}
Your problem is here
class orientation_adj extends Application
And here
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
controller = new Controller(getActivity().getApplicationContext());
Your Application class isn't the context that implemented the interface, I assume the Activity is
In that case, you only need
controller = new Controller(getActivity());
After that, set up some additional log statements and breakpoints to debug the callback code better
I am trying to implement callback between AsyncTask and Fragment but cannot find correct info how to do it. The issue is that all callback implementations are between activity and asynctask but I need between fragment and asynctask. Could someone give me small working example how to implement it without activity.
My action structure: Fragment call DialogFragment -> choose something and send server request to async task -> async task process everything and update view and some variables. My main problem is that I call prepareData() only once in onCreate and when I walk between other fragment and returns come back I see old data. That is to say there is not enough to update only view in onPost of asynctask. It will be good to have callback which will update the whole variables.
public class TermsAndConditionsFragment extends SherlockFragment implements OnClickListener, OnTouchListener, OnItemClickListener, onTaskListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fm = getSherlockActivity().getSupportFragmentManager();
prepareData();
}
public void prepareData() {
termsAndConditionsM = new TermsAndConditionsManager(getSherlockActivity());
termsAndConditions = termsAndConditionsM.getTermsAndConditions();
if (termsAndConditions != null) {
int totalPayments = Integer.valueOf(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
if (totalPayments > 0) {
paymentsData = termsAndConditionsM.getpayments();
if (paymentsData != null) {
payments = new ArrayList<Payment>();
for (int i = 1; i <= totalPayments; i++) {
paymentValues = new Payment();
paymentValues.setPaymentID(Integer.valueOf(paymentsData.get(ServerAPI.PAYMENT_NO + "_" + i)));
paymentValues.setPaymentDate(paymentsData.get(ServerAPI.PAYMENT_DATE + "_" + i));
paymentValues.setPaymentTotalAmount(paymentsData.get(ServerAPI.PAYMENT_TOTAL + "_" + i));
payments.add(paymentValues);
}
}
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = init(inflater, container);
if (payments != null || termsAndConditions != null)
updateTermsAndConditionsView();
return rootView;
}
private View init(LayoutInflater inflater, ViewGroup container) {
rootView = inflater.inflate(R.layout.fragment_terms_and_conditions, container, false);
...
return rootView;
}
public void updateTermsAndConditionsView() {
etHowMuch.setText("£" + termsAndConditions.get(ServerAPI.AMOUNT_OF_CREDIT));
etForHowLong.setText(Helpers.ConvertDays2Date(Integer.valueOf(termsAndConditions.get(ServerAPI.TERM_OF_AGREEMENT_IN_DAYS))));
PaymentAdapter adapter = new PaymentAdapter(getSherlockActivity(), R.layout.custom_loan_item, payments);
lvPayments.setAdapter(adapter);
tvNoOfPayments.setText(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
tvFirstPayment.setText(termsAndConditions.get(ServerAPI.FIRST_PAYMENT_DATE));
tvTotalRepayable.setText("£" + termsAndConditions.get(ServerAPI.TOTAL_REPAYABLE));
}
#Override
public void onClick(View v) {
ft = fm.beginTransaction();
howMuch = etHowMuch.getText().toString();
forHowLong = etForHowLong.getText().toString();
switch (v.getId()) {
case R.id.etHowMuch:
f = new NumberPaymentsPickerFragment();
args = new Bundle();
args.putInt(Const.HOW_MUCH, Integer.valueOf(howMuch.replace("£", "")));
args.putDouble(ServerAPI.PAYMENT_STEP, Const.PAYMENT_STEP);
args.putString(Const.STATE, ServerAPI.TERMS_AND_CONDITIONS);
f.setArguments(args);
f.setTargetFragment(this, DIALOG_FRAGMENT);
f.show(getActivity().getSupportFragmentManager(), Const.HOW_MUCH);
break;
case R.id.etForHowLong:
f = new NumberPaymentsPickerFragment();
args = new Bundle();
args.putInt(Const.FOR_HOW_LONG, Integer.valueOf(Helpers.ConvertDate2Days(forHowLong)));
args.putDouble(ServerAPI.PAYMENT_STEP, Const.PAYMENT_STEP);
args.putString(Const.STATE, ServerAPI.TERMS_AND_CONDITIONS);
f.setArguments(args);
f.setTargetFragment(this, DIALOG_FRAGMENT);
f.show(getActivity().getSupportFragmentManager(), Const.FOR_HOW_LONG);
break;
case R.id.tvPersonalDetails:
sfm.saveCurFragment(ServerAPI.PERSONAL_DETAILS, 0);
ft.replace(android.R.id.content, new PersonalDetailsFragment(), ServerAPI.PERSONAL_DETAILS).addToBackStack(null).commit();
break;
case R.id.tvAgreementDetails:
sfm.saveCurFragment(ServerAPI.AGREEMENT_DETAILS, 0);
ft.replace(android.R.id.content, new AgreementDetailsFragment(), ServerAPI.AGREEMENT_DETAILS).addToBackStack(null).commit();
break;
case R.id.bApply:
break;
}
#Override
public void onUpdateData() {
Log.d(TAG, "Update data");
}
}
DialogFragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
...
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
return createDialog(v, R.string.for_how_long, etHowMuch, etForHowLong, etPromotionCode);
}
return null;
}
private Dialog createDialog(View view, int titleResID, final EditText howMuchField, final EditText forHowLongField, final EditText promotionCodeField) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(titleResID);
builder.setView(view);
builder.setPositiveButton(R.string.set, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
doShowProgress();
}
private void doShowProgress() {
ExecuteServerTaskBackground task = new
ExecuteServerTaskBackground(getActivity());
task.action = ServerAPI.GET_TERMS_AND_CONDITIONS;
onTaskListener listener = new onTaskListener() {
#Override
public void onUpdateData() {
Log.d(TAG, "Updaaate");
}
};
task.setListener(listener);
task.args = args;
task.execute();
}
}).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
return builder.create();
}
AsyncTask:
onTaskListener mListener;
public interface onTaskListener {
void onUpdateData();
}
public void setListener(onTaskListener listener){
mListener = listener;
}
public ExecuteServerTaskBackground(Activity activity) {
this.mActivity = activity;
this.mContext = activity.getApplicationContext();
}
#Override
protected void onPreExecute() {
pb = (ProgressBar) mActivity.findViewById(R.id.progressBar1);
pb.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(Void... params) {
ServerAPI server = new ServerAPI(mContext);
if (!args.isEmpty())
server.serverRequest(action, args);
else
server.serverRequest(action, null);
return null;
}
#Override
protected void onPostExecute(Void result) {
mListener.onUpdateData();
//There is I just update view but how to update whole variables throughtout callback?
// tvNoOfPayments = (TextView) mActivity.findViewById(R.id.tvNoOfPaymentsValue);
// tvFirstPayment = (TextView) mActivity.findViewById(R.id.tvFirstPaymentValue);
// tvTotalRepayable = (TextView) mActivity.findViewById(R.id.tvTotalRepayableValue);
//
// lvPayments = (ListView) mActivity.findViewById(R.id.lvData);
//
// termsConditionsM = new TermsAndConditionsManager(mContext);
//
// termsAndConditions = termsConditionsM.getTermsAndConditions();
//
// int totalPayments = Integer.valueOf(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
//
// if (totalPayments > 0) {
// if (termsAndConditions != null) {
// tvNoOfPayments.setText(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
// tvFirstPayment.setText(termsAndConditions.get(ServerAPI.FIRST_PAYMENT_DATE));
// tvTotalRepayable.setText("£" + termsAndConditions.get(ServerAPI.TOTAL_REPAYABLE));
// }
//
// paymentsData = termsConditionsM.getpayments();
//
// if (paymentsData != null) {
// Log.d(TAG, paymentsData.toString());
//
// payments = new ArrayList<Payment>();
//
// for (int i = 1; i <= totalPayments; i++) {
// paymentValues = new Payment();
// paymentValues.setPaymentID(Integer.valueOf(paymentsData.get(ServerAPI.PAYMENT_NO + "_" + i)));
// paymentValues.setPaymentDate(paymentsData.get(ServerAPI.PAYMENT_DATE + "_" + i));
// paymentValues.setPaymentTotalAmount(paymentsData.get(ServerAPI.PAYMENT_TOTAL + "_" + i));
// payments.add(paymentValues);
// }
//
// PaymentAdapter adapter = new PaymentAdapter(mContext, R.layout.custom_loan_item, payments);
// lvPayments.setAdapter(adapter);
// }
//
}
pb.setVisibility(View.GONE);
super.onPostExecute(result);
}
Without taking your code in consideration I will post the most essential to make a functional callback.
TestFragment:
public class TestFragment extends Fragment {
/* Skipping most code and I will only show you the most essential. */
private void methodThatStartsTheAsyncTask() {
TestAsyncTask testAsyncTask = new TestAsyncTask(new FragmentCallback() {
#Override
public void onTaskDone() {
methodThatDoesSomethingWhenTaskIsDone();
}
});
testAsyncTask.execute();
}
private void methodThatDoesSomethingWhenTaskIsDone() {
/* Magic! */
}
public interface FragmentCallback {
public void onTaskDone();
}
}
TestAsyncTask:
public class TestAsyncTask extends AsyncTask<Void, Void, Void> {
private FragmentCallback mFragmentCallback;
public TestAsyncTask(FragmentCallback fragmentCallback) {
mFragmentCallback = fragmentCallback;
}
#Override
protected Void doInBackground(Void... params) {
/* Do your thing. */
return null;
}
#Override
protected void onPostExecute(Void result) {
mFragmentCallback.onTaskDone();
}
}
I am trying to make a volley request to api's url. The problem is that data is fetched appropriately, but every time data set updates, the whole recycler view refreshes again and begins from the start; in the docs it is mentioned that use notifyDataSetChanged() as the last resort. How can it be avoided and what are the best practices for such tasks? Any design pattern that should be followed?
Here is the Fragment Code :-
public class PageFragment extends Fragment implements SortDialogCallback {
private static final String TAG = PageFragment.class.getSimpleName();
/**
* Unsplash API, By Default=10
*/
private static final String per_page = "10";
public static String order_By;
/**
* Unsplash API call parameter, By Default=latest
* Change it in Pager Fragment, based on Tab tapped
*/
RecyclerView recyclerView;
ImageAdapter imageAdapter;
GridLayoutManager layoutManager;
EndlessRecyclerViewScrollListener scrollListener;
FloatingActionButton actionButton;
FrameLayout no_internet_container;
Bundle savedInstanceState;
// Attaching Handler to the main thread
Handler handler = new Handler();
boolean shouldHandlerRunAgain = true;
private ArrayList<DataModel> model;
/**
* Handler is attached to the Main Thread and it's message queue, because it is the one who created it.
* <p>
* Handler is responsible for checking every second that are we connected to internet, and if we are, then :-
* 1. Then we remove empty view
* 2. Make the network call
* 3. Stop handler from posting the code again using shouldHandlerRunAgain variable
* 3.1 This is a kill switch otherwise handler will post the runnable again and again to the message queue, which will be executed as soon as it reaches the looper
* <p>
* Handler removeCallbacks is used to remove all the pending runnables in the Message Queue
*/
Runnable job = new Runnable() {
#Override
public void run() {
Log.d(TAG, "Thread run " + job.hashCode());
swapViews();
if (shouldHandlerRunAgain)
handler.postDelayed(job, HANDLER_DELAY_TIME);
}
};
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("ORDER_BY", order_By);
}
#Override
public void onResume() {
super.onResume();
if (handler != null)
handler.post(job);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "Starting Handler");
layoutManager = new GridLayoutManager(getContext(), 2);
scrollListener = new EndlessRecyclerViewScrollListener(layoutManager) {
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
Log.w(TAG, "On load More Called with page number " + page);
loadDataUsingVolley(page, order_By);
}
};
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.search:
Toast.makeText(getContext(), "Async task", Toast.LENGTH_SHORT).show();
break;
default:
Toast.makeText(getContext(), "Invalid Options", Toast.LENGTH_SHORT).show();
}
return true;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_page_fragment, menu);
}
private void swapViews() {
if (detectConnection(getContext()) == false) {
recyclerView.setVisibility(View.INVISIBLE);
actionButton.setVisibility(View.INVISIBLE);
no_internet_container.setVisibility(View.VISIBLE);
} else {
Log.d(TAG, "Removing callbacks from handler and stopping it from posting");
shouldHandlerRunAgain = false;
handler.removeCallbacks(job, null);
handler = null;
recyclerView.setVisibility(View.VISIBLE);
actionButton.setVisibility(View.VISIBLE);
no_internet_container.setVisibility(View.INVISIBLE);
if (savedInstanceState != null) {
loadDataUsingVolley(1, savedInstanceState.getString("ORDER_BY"));
} else {
order_By = "latest";
loadDataUsingVolley(1, order_By);
}
}
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, final Bundle savedInstanceState) {
this.savedInstanceState = savedInstanceState;
View view = inflater.inflate(R.layout.fragment_page, container, false);
actionButton = (FloatingActionButton) view.findViewById(R.id.sort_button);
actionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SortDialog sortDialog = new SortDialog();
sortDialog.setTargetFragment(PageFragment.this, 911);
sortDialog.show(getChildFragmentManager(), "sortfragment");
}
});
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
recyclerView.setHasFixedSize(true);
no_internet_container = (FrameLayout) view.findViewById(R.id.no_internet_container);
return view;
}
void setUpRecyclerView() {
if (imageAdapter == null)
imageAdapter = new ImageAdapter(getContext(), (model==null)?new ArrayList<DataModel>():model);
recyclerView.setAdapter(imageAdapter);
recyclerView.setLayoutManager(layoutManager);
recyclerView.addOnScrollListener(scrollListener);
}
void loadDataUsingVolley(int page, String order_by) {
final ProgressDialog dialog = ProgressDialog.show(getContext(), "Wallser", "Loading");
RequestQueue requestQueue = Volley.newRequestQueue(getContext());
String URL = "https://api.unsplash.com/photos/?page=" + page + "&client_id=" + api_key + "&per_page=" + per_page + "&order_by=" + order_by;
Log.d(TAG, URL);
JsonArrayRequest objectRequest = new JsonArrayRequest(Request.Method.GET, URL, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray array) {
int len = array.length();
if (model == null)
model = new ArrayList<>();
for (int i = 0; i < len; i++) {
try {
JSONObject object = array.getJSONObject(i);
String id = object.getString("id");
JSONObject object1 = object.getJSONObject("urls");
String imageURL = object1.getString("regular");
JSONObject object2 = object.getJSONObject("links");
String downloadURL = object2.getString("download");
model.add(new DataModel(imageURL, downloadURL, id));
Log.d(TAG, downloadURL);
} catch (JSONException e) {
e.printStackTrace();
}
}
if (dialog != null) {
dialog.dismiss();
}
Log.d(TAG, model.size() + "");
setUpRecyclerView();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
dialog.dismiss();
Toast.makeText(getContext(), "" + error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
requestQueue.add(objectRequest);
}
/**
* marks a new network call to Unsplash API
* Thus, set model array list to null, to start fresh.
* as model is reset, ImageAdapter also needs to start fresh.
*
* #param order_by
*/
#Override
public void onDialogFinish(String order_by) {
model = null;
imageAdapter=null;
order_By = order_by;
loadDataUsingVolley(1, order_By);
}
}
I'm stuck with communication between activity and fragment using interface. I have created activity with child fragment. I wanna do some stuff with continuous thread defined in activity and during that thread when I'm getting some result at that time I wanna trigger to child fragment to do something.
My Container Activity
public class MySpaceActivity extends BaseDrawerActivity {
private OnSetLastSeenListener mListner;
public static Thread mThread = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setHeaders(Const.MY_SPACE);
super.setSubmenus(Const.MY_SPACE,
Utils.getSubmenuList(Const.MY_SPACE, MySpaceActivity.this),
submenuBean);
// super.attachFragment(submenuBean);
}
#Override
public void setHeaderSubMenu(SubmenuBean subMenuBean) {
// txt_submenu.setText(subMenuBean.getSubmenu_name());
this.submenuBean = subMenuBean;
Log.print("::::: setHeaderSubMenu ::::");
super.attachFragment(submenuBean);
}
public void setsubFragment(SubmenuBean subMenuBean) {
this.submenuBean = subMenuBean;
super.attachSubFragment(submenuBean);
}
#Override
public void onBackPressed() {
super.onBackPressed();
popLastFragment();
}
private void popLastFragment() {
if (super.getNumberOfChilds() > 1) {
super.popSubFragment();
} else {
finish();
}
}
#Override
protected Fragment getFragement() {
StudentsFragment fragment = new StudentsFragment(Const.MY_SPACE,
getSubmenubean());
return fragment;
}
public SubmenuBean getSubmenubean() {
return submenuBean;
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
mThread = new Thread(new CountDownTimer(MySpaceActivity.this));
mThread.start();
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
if (mThread.isAlive()) {
mThread.interrupt();
mThread = null;
}
}
public void updateLastSeen(){
Log.print("::::::Call Interface::::::");
mListner.updateLastSeen();
}
class CountDownTimer implements Runnable {
private Context mContext;
private JSONObject mJsonObject;
private JSONArray mJsonArray;
public CountDownTimer(Context mContext) {
this.mContext = mContext;
}
// #Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
HttpChatLastSeen mChat = new HttpChatLastSeen();
mJsonObject = mChat.Http_ChatLastSeen(mContext);
String mResult = mJsonObject.getString("Result");
if (mResult.equalsIgnoreCase(String
.valueOf(Const.RESULT_OK))) {
mJsonArray = mJsonObject.getJSONArray("UserData");
for (int i = 0; i < mJsonArray.length(); i++) {
mJsonObject = mJsonArray.getJSONObject(i);
new DbStudentMasterBll(mContext).update(
"last_seen", mJsonObject
.getString("LastSeen"), Integer
.parseInt(mJsonObject
.getString("UserId")));
}
} else {
Log.print("MY LAST SEEN Response : "
+ mJsonObject.toString());
}
updateLastSeen();
Thread.sleep(15000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
Log.print("ChatLastSeenThread : ", e.getMessage());
}
}
}
}
}
My Child Fragment With Interface :
public class StudentsFragment extends Fragment implements OnSetLastSeenListener{
TextView txt_submenu;
ListView list_students;
SubmenuBean submenuBean;
int Mainmenu;
MySpaceActivity mMySpaceActivity;
ArrayList<DbStudentMasterBean> studentsList;
StudentsAdapter mAdapter = null;
OnSetLastSeenListener mListner;
public StudentsFragment() {
super();
}
public StudentsFragment(int Mainmenu, SubmenuBean submenuBean) {
this.submenuBean = submenuBean;
this.Mainmenu = Mainmenu;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_students, container,
false);
mMySpaceActivity = (MySpaceActivity) getActivity();
txt_submenu = (TextView) view.findViewById(R.id.txt_submenu);
txt_submenu.setText(submenuBean.getSubmenu_name());
txt_submenu.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mMySpaceActivity.openDrawer();
}
});
list_students = (ListView) view.findViewById(R.id.list_colleagues);
studentsList = new DbStudentMasterBll(getActivity()).getAllRecords();
mAdapter = new StudentsAdapter(getActivity(), studentsList, handler);
list_students.setAdapter(mAdapter);
list_students.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
DbStudentMasterBean bean = (DbStudentMasterBean) parent
.getAdapter().getItem(position);
Message msg = new Message();
msg.what = CHAT;
msg.obj = bean;
handler.sendMessage(msg);
}
});
return view;
}
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case CHAT:
submenuBean.setTag(VIEWCHATSTUDENT);
DbStudentMasterBean bean = (DbStudentMasterBean) msg.obj;
mMySpaceActivity.setsubFragment(submenuBean);
break;
}
};
};
#Override
public void updateLastSeen() {
// TODO Auto-generated method stub
Log.print("!!!!!!!!!Refresh Adapter!!!!!!!!!!!");
mAdapter.notifyDataSetChanged();
}
}
My Interface :
public interface OnSetLastSeenListener {
public void updateLastSeen();
}
So I have implemented interface OnSetLastSeenListener with my child fragment StudentsFragment . Now I'm calling method of tht interface updateLastSeen() from my container activity with thread. But it is not getting trigger to child fragment where I have implemented interface. So I don't know whether it is good way to communicate or not? Let me take your help to suggest on this solution or best way to communicate from child fragment to parent activity.
Thanks,
It is better to use interface when you want to communicate something from Fragment to Activity and not vice versa.
In your case, you can directly call the method in Fragment from Activity through fragment object. No need to use interface.
Something like this (For static fragments)
StudentsFragment fragment = (StudentsFragment) getFragmentManager()
.findFragmentById(R.id.fragmentid);
if (fragment != null && fragment.isInLayout()) {
fragment.updateLastSeen();
}
For dynamic fragment you can use the fragment object directly.
I am trying to implement callback between AsyncTask and Fragment but cannot find correct info how to do it. The issue is that all callback implementations are between activity and asynctask but I need between fragment and asynctask. Could someone give me small working example how to implement it without activity.
My action structure: Fragment call DialogFragment -> choose something and send server request to async task -> async task process everything and update view and some variables. My main problem is that I call prepareData() only once in onCreate and when I walk between other fragment and returns come back I see old data. That is to say there is not enough to update only view in onPost of asynctask. It will be good to have callback which will update the whole variables.
public class TermsAndConditionsFragment extends SherlockFragment implements OnClickListener, OnTouchListener, OnItemClickListener, onTaskListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fm = getSherlockActivity().getSupportFragmentManager();
prepareData();
}
public void prepareData() {
termsAndConditionsM = new TermsAndConditionsManager(getSherlockActivity());
termsAndConditions = termsAndConditionsM.getTermsAndConditions();
if (termsAndConditions != null) {
int totalPayments = Integer.valueOf(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
if (totalPayments > 0) {
paymentsData = termsAndConditionsM.getpayments();
if (paymentsData != null) {
payments = new ArrayList<Payment>();
for (int i = 1; i <= totalPayments; i++) {
paymentValues = new Payment();
paymentValues.setPaymentID(Integer.valueOf(paymentsData.get(ServerAPI.PAYMENT_NO + "_" + i)));
paymentValues.setPaymentDate(paymentsData.get(ServerAPI.PAYMENT_DATE + "_" + i));
paymentValues.setPaymentTotalAmount(paymentsData.get(ServerAPI.PAYMENT_TOTAL + "_" + i));
payments.add(paymentValues);
}
}
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = init(inflater, container);
if (payments != null || termsAndConditions != null)
updateTermsAndConditionsView();
return rootView;
}
private View init(LayoutInflater inflater, ViewGroup container) {
rootView = inflater.inflate(R.layout.fragment_terms_and_conditions, container, false);
...
return rootView;
}
public void updateTermsAndConditionsView() {
etHowMuch.setText("£" + termsAndConditions.get(ServerAPI.AMOUNT_OF_CREDIT));
etForHowLong.setText(Helpers.ConvertDays2Date(Integer.valueOf(termsAndConditions.get(ServerAPI.TERM_OF_AGREEMENT_IN_DAYS))));
PaymentAdapter adapter = new PaymentAdapter(getSherlockActivity(), R.layout.custom_loan_item, payments);
lvPayments.setAdapter(adapter);
tvNoOfPayments.setText(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
tvFirstPayment.setText(termsAndConditions.get(ServerAPI.FIRST_PAYMENT_DATE));
tvTotalRepayable.setText("£" + termsAndConditions.get(ServerAPI.TOTAL_REPAYABLE));
}
#Override
public void onClick(View v) {
ft = fm.beginTransaction();
howMuch = etHowMuch.getText().toString();
forHowLong = etForHowLong.getText().toString();
switch (v.getId()) {
case R.id.etHowMuch:
f = new NumberPaymentsPickerFragment();
args = new Bundle();
args.putInt(Const.HOW_MUCH, Integer.valueOf(howMuch.replace("£", "")));
args.putDouble(ServerAPI.PAYMENT_STEP, Const.PAYMENT_STEP);
args.putString(Const.STATE, ServerAPI.TERMS_AND_CONDITIONS);
f.setArguments(args);
f.setTargetFragment(this, DIALOG_FRAGMENT);
f.show(getActivity().getSupportFragmentManager(), Const.HOW_MUCH);
break;
case R.id.etForHowLong:
f = new NumberPaymentsPickerFragment();
args = new Bundle();
args.putInt(Const.FOR_HOW_LONG, Integer.valueOf(Helpers.ConvertDate2Days(forHowLong)));
args.putDouble(ServerAPI.PAYMENT_STEP, Const.PAYMENT_STEP);
args.putString(Const.STATE, ServerAPI.TERMS_AND_CONDITIONS);
f.setArguments(args);
f.setTargetFragment(this, DIALOG_FRAGMENT);
f.show(getActivity().getSupportFragmentManager(), Const.FOR_HOW_LONG);
break;
case R.id.tvPersonalDetails:
sfm.saveCurFragment(ServerAPI.PERSONAL_DETAILS, 0);
ft.replace(android.R.id.content, new PersonalDetailsFragment(), ServerAPI.PERSONAL_DETAILS).addToBackStack(null).commit();
break;
case R.id.tvAgreementDetails:
sfm.saveCurFragment(ServerAPI.AGREEMENT_DETAILS, 0);
ft.replace(android.R.id.content, new AgreementDetailsFragment(), ServerAPI.AGREEMENT_DETAILS).addToBackStack(null).commit();
break;
case R.id.bApply:
break;
}
#Override
public void onUpdateData() {
Log.d(TAG, "Update data");
}
}
DialogFragment:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
...
}
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
return createDialog(v, R.string.for_how_long, etHowMuch, etForHowLong, etPromotionCode);
}
return null;
}
private Dialog createDialog(View view, int titleResID, final EditText howMuchField, final EditText forHowLongField, final EditText promotionCodeField) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(titleResID);
builder.setView(view);
builder.setPositiveButton(R.string.set, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
doShowProgress();
}
private void doShowProgress() {
ExecuteServerTaskBackground task = new
ExecuteServerTaskBackground(getActivity());
task.action = ServerAPI.GET_TERMS_AND_CONDITIONS;
onTaskListener listener = new onTaskListener() {
#Override
public void onUpdateData() {
Log.d(TAG, "Updaaate");
}
};
task.setListener(listener);
task.args = args;
task.execute();
}
}).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
return builder.create();
}
AsyncTask:
onTaskListener mListener;
public interface onTaskListener {
void onUpdateData();
}
public void setListener(onTaskListener listener){
mListener = listener;
}
public ExecuteServerTaskBackground(Activity activity) {
this.mActivity = activity;
this.mContext = activity.getApplicationContext();
}
#Override
protected void onPreExecute() {
pb = (ProgressBar) mActivity.findViewById(R.id.progressBar1);
pb.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(Void... params) {
ServerAPI server = new ServerAPI(mContext);
if (!args.isEmpty())
server.serverRequest(action, args);
else
server.serverRequest(action, null);
return null;
}
#Override
protected void onPostExecute(Void result) {
mListener.onUpdateData();
//There is I just update view but how to update whole variables throughtout callback?
// tvNoOfPayments = (TextView) mActivity.findViewById(R.id.tvNoOfPaymentsValue);
// tvFirstPayment = (TextView) mActivity.findViewById(R.id.tvFirstPaymentValue);
// tvTotalRepayable = (TextView) mActivity.findViewById(R.id.tvTotalRepayableValue);
//
// lvPayments = (ListView) mActivity.findViewById(R.id.lvData);
//
// termsConditionsM = new TermsAndConditionsManager(mContext);
//
// termsAndConditions = termsConditionsM.getTermsAndConditions();
//
// int totalPayments = Integer.valueOf(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
//
// if (totalPayments > 0) {
// if (termsAndConditions != null) {
// tvNoOfPayments.setText(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS));
// tvFirstPayment.setText(termsAndConditions.get(ServerAPI.FIRST_PAYMENT_DATE));
// tvTotalRepayable.setText("£" + termsAndConditions.get(ServerAPI.TOTAL_REPAYABLE));
// }
//
// paymentsData = termsConditionsM.getpayments();
//
// if (paymentsData != null) {
// Log.d(TAG, paymentsData.toString());
//
// payments = new ArrayList<Payment>();
//
// for (int i = 1; i <= totalPayments; i++) {
// paymentValues = new Payment();
// paymentValues.setPaymentID(Integer.valueOf(paymentsData.get(ServerAPI.PAYMENT_NO + "_" + i)));
// paymentValues.setPaymentDate(paymentsData.get(ServerAPI.PAYMENT_DATE + "_" + i));
// paymentValues.setPaymentTotalAmount(paymentsData.get(ServerAPI.PAYMENT_TOTAL + "_" + i));
// payments.add(paymentValues);
// }
//
// PaymentAdapter adapter = new PaymentAdapter(mContext, R.layout.custom_loan_item, payments);
// lvPayments.setAdapter(adapter);
// }
//
}
pb.setVisibility(View.GONE);
super.onPostExecute(result);
}
Without taking your code in consideration I will post the most essential to make a functional callback.
TestFragment:
public class TestFragment extends Fragment {
/* Skipping most code and I will only show you the most essential. */
private void methodThatStartsTheAsyncTask() {
TestAsyncTask testAsyncTask = new TestAsyncTask(new FragmentCallback() {
#Override
public void onTaskDone() {
methodThatDoesSomethingWhenTaskIsDone();
}
});
testAsyncTask.execute();
}
private void methodThatDoesSomethingWhenTaskIsDone() {
/* Magic! */
}
public interface FragmentCallback {
public void onTaskDone();
}
}
TestAsyncTask:
public class TestAsyncTask extends AsyncTask<Void, Void, Void> {
private FragmentCallback mFragmentCallback;
public TestAsyncTask(FragmentCallback fragmentCallback) {
mFragmentCallback = fragmentCallback;
}
#Override
protected Void doInBackground(Void... params) {
/* Do your thing. */
return null;
}
#Override
protected void onPostExecute(Void result) {
mFragmentCallback.onTaskDone();
}
}