This app have a fragment that does CRUD operations on a single table database.
It is done on an class that draws a FAB and a recyclerview.
The FAB open an alertDialog with a insert form.
The recyclerview shows the database rows as cardviews. Each cardview have an edit button and a delete button.
The edit button open a alertdialog with the edit form in it.
The database stores journeys that each have a starting point and an ending point.
When entering or editing the places, user get suggestions.
For this I was using Google Places Web Service API but got to my attention that I must use Google Places API for Android and hence GoogleApiClient
Note that the app is working fine, doing the CRUD successfully and even getting the directions suggestions from Web Services.
I was able to make the insert form use the correct API, but not the edit form.
Here is the fragment code:
public class RecyclerFragment extends Fragment
implements AlertDialog.OnClickListener,
GoogleApiClient.OnConnectionFailedListener,
GoogleApiClient.ConnectionCallbacks {
private static final String TAG = "RecyclerFragment";
RunDbHelper runDbHelper; // Database helper class
RecyclerView recyclerView;
RecyclerViewAdapter recyclerViewAdapter;
private OnOkButtonListener mCallback;
private GoogleApiClient mGoogleApiClient;
private PlaceArrayAdapter mPlaceArrayAdapter;
private static final int GOOGLE_API_CLIENT_ID = 0;
private static final LatLngBounds BOUNDS_MOUNTAIN_VIEW = new LatLngBounds(
new LatLng(37.398160, -122.180831), new LatLng(37.430610, -121.972090));
private static LatLngBounds BOUNDS_AUTOCOMPLETE;
public RecyclerFragment() {
this.mCallback = null;
}
// main activity calls this method to pass the location so it can calculate bounds for the direction suggestions
public void setAutocompleteBounds(LatLng centerLatLng){
if (centerLatLng!= null && !centerLatLng.toString().isEmpty()){
Double latSW, lngSW, lngNE, latNE;
latSW = centerLatLng.latitude-.5;
lngSW = centerLatLng.latitude-.5;
lngNE = centerLatLng.latitude+.5;
latNE = centerLatLng.latitude+.5;
BOUNDS_AUTOCOMPLETE = new LatLngBounds(
new LatLng(latSW, lngSW), new LatLng(latNE, lngNE));
} else {
BOUNDS_AUTOCOMPLETE = BOUNDS_MOUNTAIN_VIEW;
}
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recycler, container, false);
try {
mGoogleApiClient = new GoogleApiClient.Builder(getContext())
.addApi(Places.GEO_DATA_API)
.enableAutoManage(getActivity(), GOOGLE_API_CLIENT_ID, this)
.addConnectionCallbacks(this)
.build();
} catch ( Exception e) {
Log.i(TAG, "onCreateView: " + e);
}
mPlaceArrayAdapter = new PlaceArrayAdapter(getContext(), android.R.layout.simple_list_item_1,
BOUNDS_AUTOCOMPLETE, null);
runDbHelper = RunDbHelper.getInstance(getContext());
List<RunData> mList = runDbHelper.getAllRuns();
recyclerViewAdapter = new RecyclerViewAdapter(getContext(), mList);
recyclerView = (RecyclerView) view.findViewById(R.id.rvRunList);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(recyclerViewAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.fabAdd);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Data entry dialog to insert new runs into database
dialogInsertRun();
}
});
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
public void dialogInsertRun() {
// Get the Activity for layout inflater as this dialog runs inside a fragment
LayoutInflater inflater = LayoutInflater.from(getActivity());
final View view = inflater.inflate(R.layout.dialog_new_run, null);
// Dialog Builder
AlertDialog.Builder addRunDialog = new AlertDialog.Builder(getActivity());
addRunDialog.setTitle(R.string.dialog_insert_run_title)
.setView(view);
// Data entry field objects
final EditText runParcelEditText = (EditText) view.findViewById(R.id.new_run_parcel);
final AutoCompleteTextView collectAddressACTV = (AutoCompleteTextView) view.findViewById(R.id.actv_new_collect_address);
final EditText collectPersonEditText = (EditText) view.findViewById(R.id.new_collect_person);
final AutoCompleteTextView deliveryAddressACTV = (AutoCompleteTextView) view.findViewById(R.id.actv_new_delivery_address);
final EditText deliveryPersonEditText = (EditText) view.findViewById(R.id.new_delivery_person);
collectAddressACTV.setThreshold(3);
collectAddressACTV.setOnItemClickListener(mAutocompleteClickListener);
collectAddressACTV.setAdapter(mPlaceArrayAdapter);
deliveryAddressACTV.setThreshold(3);
deliveryAddressACTV.setOnItemClickListener(mAutocompleteClickListener);
deliveryAddressACTV.setAdapter(mPlaceArrayAdapter);
addRunDialog.setPositiveButton(R.string.button_positive, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
RunData runData = new RunData(); // POJO that holds data from database
runData.run_parcel = getStringOrEmpty(runParcelEditText);
runData.collect_person = getStringOrEmpty(collectPersonEditText);
runData.collect_address = getStringOrEmpty(collectAddressACTV);
runData.delivery_person = getStringOrEmpty(deliveryPersonEditText);
runData.delivery_address = getStringOrEmpty(deliveryAddressACTV);
// must insert at least one of the places (starting or ending point) or both
if (!(runData.collect_address.isEmpty() && runData.delivery_address.isEmpty())) {
runData = runDbHelper.insertRun(runData, getActivity());
if (runData != null) {
cardViewMessageIsEmpty.setVisibility(View.INVISIBLE);
recyclerViewAdapter = new RecyclerViewAdapter(getActivity(), runDbHelper.getAllRuns());
recyclerView.setAdapter(recyclerViewAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mCallback.addMarkersToMap(runData);
}
} else {
Toast.makeText(getActivity(), R.string.dialog_insert_run_toast_nowhere, Toast.LENGTH_LONG).show();
}
}
});
addRunDialog.setNegativeButton(R.string.button_negative, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
addRunDialog.create();
addRunDialog.show();
}
private String getStringOrEmpty(EditText editText) {
String mString = editText.getText().toString();
mString = (mString == null || mString.isEmpty() ? "" : mString);
return mString;
}
#Override
public void onClick(DialogInterface dialogInterface, int i) {
//Log.d(TAG, "onClick: ");
}
#Override
public void onAttach(Context context) {
if (context instanceof OnOkButtonListener) {
mCallback = (OnOkButtonListener) context; // keep a reference to eula activity for interface
} else {
throw new ClassCastException(context.toString()
+ getString(R.string.exception_onokbutton_listener));
}
super.onAttach(context);
}
public void setCustomObjectListener(OnOkButtonListener listener) {
this.mCallback = listener;
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mPlaceArrayAdapter.setGoogleApiClient(mGoogleApiClient);
Log.i(TAG, "Google Places API connected.");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e(TAG, "Google Places API connection failed with error code: "
+ connectionResult.getErrorCode());
Toast.makeText(getContext(),
"Google Places API connection failed with error code:" +
connectionResult.getErrorCode(),
Toast.LENGTH_LONG).show();
}
#Override
public void onConnectionSuspended(int i) {
mPlaceArrayAdapter.setGoogleApiClient(null);
Log.e(TAG, "Google Places API connection suspended.");
}
public interface OnOkButtonListener {
void addMarkersToMap(RunData runData);
}
private AdapterView.OnItemClickListener mAutocompleteClickListener
= new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final PlaceArrayAdapter.PlaceAutocomplete item = mPlaceArrayAdapter.getItem(position);
final String placeId = String.valueOf(item.placeId);
Log.i(TAG, "Selected: " + item.description);
PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi
.getPlaceById(mGoogleApiClient, placeId);
placeResult.setResultCallback(mUpdatePlaceDetailsCallback);
Log.i(TAG, "Fetching details for ID: " + item.placeId);
}
};
#Override
public void onDestroyView() {
super.onDestroyView();
if(mGoogleApiClient != null && mGoogleApiClient.isConnected()) {
mGoogleApiClient.stopAutoManage(getActivity());
mGoogleApiClient.disconnect();
}
}
private ResultCallback<PlaceBuffer> mUpdatePlaceDetailsCallback
= new ResultCallback<PlaceBuffer>() {
#Override
public void onResult(PlaceBuffer places) {
if (!places.getStatus().isSuccess()) {
Log.e(TAG, "Place query did not complete. Error: " +
places.getStatus().toString());
return;
}
// Selecting the first object buffer.
}
};
}
And here is the adapter code:
class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder> {
private static final String TAG = "RecyclerViewAdapter";
private Context context;
private List<RunData> dataList = new ArrayList<>();
private LayoutInflater inflater;
private RunDbHelper runDbHelper;
RecyclerViewAdapter(Context context, List<RunData> dataList1) {
this.context = context;
this.dataList = dataList1;
this.runDbHelper = RunDbHelper.getInstance(this.context);
inflater = LayoutInflater.from(context);
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View inflateView = inflater.inflate(R.layout.fragment_recycler_row, parent, false);
return new RecyclerViewHolder(inflateView);
}
#Override
public void onBindViewHolder(final RecyclerViewHolder holder, final int position) {
holder.runID.setText(dataList.get(position).run_id);
holder.collectAddress.setText(dataList.get(position).collect_address);
holder.deliveryAddress.setText(dataList.get(position).delivery_address);
holder.ivEdit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
RunData runData = new RunData();
runData.run_id = holder.runID.getText().toString();
runData.collect_address = holder.collectAddress.getText().toString();
runData.delivery_address = holder.deliveryAddress.getText().toString();
dialogEditRun(runData, position);
}
});
}
#Override
public int getItemCount() {
return dataList.size();
}
public void dialogEditRun(RunData runData, int position) {
// Get the Activity for layout inflater as this dialog runs inside a fragment
LayoutInflater inflater = LayoutInflater.from(context);
final View inflaterView = inflater.inflate(R.layout.dialog_edit_run, null);
// Data entry field objects
final String mRunID;
final AutoCompleteTextView collectAddressACTV = (AutoCompleteTextView) inflaterView.findViewById(R.id.actv_edit_collect_address);
final AutoCompleteTextView deliveryAddressACTV = (AutoCompleteTextView) inflaterView.findViewById(R.id.actv_edit_delivery_address);
mRunID = runData.run_id;
collectAddressACTV.setText(runData.collect_address);
deliveryAddressACTV.setText(runData.delivery_address);
// HERE THE FIELDS AND THE SUGGESTIONS ARE LINKED
// Set directions into recyclerViewAdapter for autocomplete
// here is still using G. Places WebService API. Should be G. Places API for Android, using GoogleApiClient
collectAddressACTV.setAdapter(new GooglePlacesAutocompleteAdapter(context, R.layout.dialog_new_run_autocomplete));
deliveryAddressACTV.setAdapter(new GooglePlacesAutocompleteAdapter(context, R.layout.dialog_new_run_autocomplete));
// Dialog Builder
AlertDialog.Builder editRunDialog = new AlertDialog.Builder(context);
editRunDialog.setTitle(R.string.dialog_update_run_title).setView(inflaterView);
editRunDialog.setPositiveButton(R.string.button_positive, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int id) {
RunData runData = new RunData();
int position = (int) run_date.getTag();
runData.run_id = mRunID;
runData.collect_address = getStringOrEmpty(collectAddressACTV);
runData.delivery_address = getStringOrEmpty(deliveryAddressACTV);
if (!(runData.collect_address.isEmpty() && runData.delivery_address.isEmpty())){
// try to update, if success update recycler.
if (runDbHelper.updateRun(runData, context)){
// atualiza o recyclerview
dataList.remove(position);
notifyItemRemoved(position);
dataList.add(position,runData);
notifyItemRangeChanged(position, dataList.size());
notifyItemInserted(position);
} else {
Toast.makeText(context, "No record updated", Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(context, "Inform at least one direction", Toast.LENGTH_SHORT).show();
}
}
});
editRunDialog.setNegativeButton(R.string.button_negative, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.cancel();
}
});
editRunDialog.create();
editRunDialog.show();
}
private String getStringOrEmpty(EditText editText) {
String mString = editText.getText().toString();
mString = (mString.isEmpty() ? "" : mString);
return mString;
}
class RecyclerViewHolder extends RecyclerView.ViewHolder {
TextView runID, collectAddress, deliveryAddress;
ImageView ivEdit;
RecyclerViewHolder(View rowView) {
super(rowView);
runID = (TextView) rowView.findViewById(R.id.runId);
collectAddress = (TextView) rowView.findViewById(R.id.collectAddress);
deliveryAddress = (TextView) rowView.findViewById(R.id.deliveryAddress);
ivEdit = (ImageView) rowView.findViewById(R.id.ivEdit);
}
}
}
When I try to add the code to instantiate the GoogleApiClient inside the reclycler adapter, at onCreateViewHolder(ViewGroup parent, int viewType), Android Studio wont let me. I cannot find the right reference for enableAutoManage
mGoogleApiClient = new GoogleApiClient.Builder(context)
.addApi(Places.GEO_DATA_API)
.enableAutoManage(HEREISTHEERROR, GOOGLE_API_CLIENT_ID, this) // nada do que tentei colocar aqui no lugar do XXXXXXX funcionou!
.addConnectionCallbacks(this)
.build();
In summary, what I want accomplished is to receive suggestions when adding or editing directions data into forms that are shown inside alertDialog.
Must use Google Places API for android, hence GoogleApiClient.
Not sure that this is the right approach, so... Any suggestions or workarounds are welcome.
I have solved the question.
There can be only one GoogleApiClient with enableAutoManage(). The other calls to the API have to deal with life cicle.
Accessing Google APIs
Related
I made a callback by interface from a viewholder to the Fragment that has created the recyclerviewadapter with that viewholder inside.
Now I'm having trouble to connect to the viewmodel (of that fragment) with:
ViewModelProviders.of(getActivity()).get(ViewModelClass.class);
because of a null pointer exception :(
I can’t catch up to the activity again after that callback from the viewholder…
How would you solve that problem?
code:
recyclerviewadapter & viewholder:
public class BoxRecyclerViewAdapter extends RecyclerView.Adapter {
public String TAG = BoxRecyclerViewAdapter.class.getSimpleName();
Context context;
private List<Car> carList;
private CallbackBox callbackBox;
// boxType: 1 = cars | 2 = damage
private int boxType = 0;
// empty constructor
BoxRecyclerViewAdapter(){
}
// constuctor to create car boxes
public BoxRecyclerViewAdapter boxRecyclerViewAdapterCar(Context _context, List<Car> _tempList) {
this.carList = _tempList;
this.context = _context;
// hide buttons
this.boxType = 1;
return this;
}
// constuctor to create damage boxes
public BoxRecyclerViewAdapter boxRecyclerViewAdapterDamage(Context _context, List<Car> _tempList) {
this.carList = _tempList;
this.context = _context;
// show buttons
this.boxType = 2;
return this;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
/*
if ( callbackBox == null ){
Log.d(TAG, "mike: in BoxRecycler - callback = null " );
} else {
Log.d(TAG, "mike: in BoxRecycler - callback = NOT NULL " + callbackBox.toString() );
}
*/
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.box_layout, parent, false);
return new ViewHolder(view, this.callbackBox);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Car UploadInfo = carList.get(position);
holder.lb_title.setText(UploadInfo.getManuf());
holder.lb1.setText(UploadInfo.getModell());
holder.lb2.setText(UploadInfo.getIdentno());
holder.lb3.setText(UploadInfo.getYear());
}
#Override
public int getItemCount() {
return carList.size();
}
// register callback regarding the box listener with the ViewHolder Method
public void registerCallBackBoxListener( CallbackBox _callbackBox ){
//Log.d(TAG, "mike: callback register - complete");
this.callbackBox = _callbackBox;
}
// ******************* class ViewHolder *********************
class ViewHolder extends RecyclerView.ViewHolder {
private Context context;
private CallbackBox callbackBox;
private TextView lb_title;
private TextView lb1;
private TextView lb2;
private TextView lb3;
private TextView lb1_desc;
private TextView lb2_desc;
private TextView lb3_desc;
private Button bt_accept;
private Button bt_reject;
private ImageButton ibt_menu_edit;
private ImageButton ibt_menu_del;
private LinearLayout layout_box_buttons;
private ViewHolder(final View itemView, CallbackBox _callbackBox) {
super(itemView);
this.callbackBox = _callbackBox;
this.context = itemView.getContext();
lb_title = (TextView) itemView.findViewById(R.id.lb_title);
lb1 = (TextView) itemView.findViewById(R.id.lb1);
lb2 = (TextView) itemView.findViewById(R.id.lb2);
lb3 = (TextView) itemView.findViewById(R.id.lb3);
lb1_desc = (TextView) itemView.findViewById(R.id.lb1_desc);
lb2_desc = (TextView) itemView.findViewById(R.id.lb2_desc);
lb3_desc = (TextView) itemView.findViewById(R.id.lb3_desc);
bt_accept = (Button) itemView.findViewById(R.id.bt_accept);
bt_reject = (Button) itemView.findViewById(R.id.bt_reject);
ibt_menu_edit = (ImageButton) itemView.findViewById(R.id.ibt_menu_edit);
ibt_menu_del = (ImageButton) itemView.findViewById(R.id.ibt_menu_del);
layout_box_buttons = (LinearLayout) itemView.findViewById(R.id.layout_box_buttons);
// configure box layout
switch (boxType) {
// car
case 1:
// hide the layout with the buttons
layout_box_buttons.setVisibility( View.GONE );
lb1_desc.setText(R.string.txt_car_modell);
lb2_desc.setText(R.string.txt_car_identno);
lb3_desc.setText(R.string.txt_car_year);
break;
// damage
case 2:
layout_box_buttons.setVisibility( View.VISIBLE );
break;
}
// ******************** Listeners ****************
// start edit fragment
ibt_menu_edit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(context, "menu button edit clicked", Toast.LENGTH_SHORT).show();
//Log.d(TAG, "mike: in edit onClick Listener - toString: " + callbackBox.toString() );
callbackBox.onCarEdit( lb2.getText().toString() );
}
});
// start delete (path to identNo)
ibt_menu_del.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(context, "menu button del clicked", Toast.LENGTH_SHORT).show();
callbackBox.onCarDelete( lb2.getText().toString() );
}
});
// onClickListeners - Buttons
// start accept
bt_accept.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "accept button clicked", Toast.LENGTH_SHORT).show();
}
});
// sharing reject
bt_reject.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "reject button clicked", Toast.LENGTH_SHORT).show();
}
});
}
}
}
Fragment & callback:
public class FragmentCarDetailRequest extends Fragment implements CallbackBox{
public String TAG = FragmentCarDetailRequest.class.getSimpleName();
public ViewModelClass viewModelClass;
// Creating RecyclerView & adapter
RecyclerView recyclerView;
RecyclerView.Adapter adapter;
// Creating Progress dialog
ProgressDialog progressDialog;
// Creating List of Events class
List<Car> carList = new ArrayList<>();
private String userUid;
public static FragmentCarDetailRequest newInstance() {
return new FragmentCarDetailRequest();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
// Defines the xml file for the fragment
return inflater.inflate(R.layout.car_recyclerview, container, false);
}
#Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
// Setup any handles to view objects here
this.viewModelClass = ViewModelProviders.of(getActivity()).get(ViewModelClass.class);
userUid = viewModelClass.getCurrentUser().getUid();
// Assign id to RecyclerView.
recyclerView = (RecyclerView) view.findViewById(R.id.car_recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
// Assign activity this to progress dialog.
progressDialog = new ProgressDialog(getContext());
progressDialog.setMessage("Daten werden geladen");
progressDialog.show();
Log.d(TAG, "mike: starting livedata request ");
LiveData<DataSnapshot> liveData = viewModelClass.getDataSnapshotLiveData("cars", userUid );
liveData.observe(this, new Observer<DataSnapshot>() {
#Override
public void onChanged(#Nullable DataSnapshot dataSnapshot) {
if (dataSnapshot != null ){
carList.clear();
// retrieve the server content to add it to the list
for (DataSnapshot postSnapshot : dataSnapshot.getChildren() ) {
Car car = postSnapshot.getValue(Car.class);
carList.add(car);
}
BoxRecyclerViewAdapter boxRecyclerViewAdapter = new BoxRecyclerViewAdapter();
// register callbacks & RecyclerViewAdapter
CallbackBox callbackBox = new FragmentCarDetailRequest();
boxRecyclerViewAdapter.registerCallBackBoxListener( callbackBox );
adapter = boxRecyclerViewAdapter.boxRecyclerViewAdapterCar( getActivity().getApplicationContext(), carList );
recyclerView.setAdapter(adapter);
progressDialog.dismiss();
}
}
});
}
#Override
public void onCarDelete(String _identNo) {
Log.d(TAG, "mike: got callback to delete car..." + viewModelClass.getCurrentUser().getUid());
}
}
--------- beginning of crash
08-03 16:05:49.623 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.wendtmichael.app2repair, PID: 6833
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.firebase.auth.FirebaseUser com.wendtmichael.app2repair.ViewModelClass.getCurrentUser()' on a null object reference
at com.wendtmichael.app2repair.FragmentCarDetailRequest.onCarDelete(FragmentCarDetailRequest.java:173)
at com.wendtmichael.app2repair.BoxRecyclerViewAdapter$ViewHolder$2.onClick(BoxRecyclerViewAdapter.java:193)
at android.view.View.performClick(View.java:5264)
at android.view.View$PerformClick.run(View.java:21297)
at android.os.Handler.handleCallback(Handler.java:743)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:150)
at android.app.ActivityThread.main(ActivityThread.java:5546)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684)
I know, this question asked many times but I am totally lost after reading some answers. I am new to Android development. I have created a Fragment and initialized and set the adapter from that fragment
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(ConfigDataloggerViewModel.class);
dataLoggerList = getResources().getStringArray(R.array.DataLoggerStringArray);
// TODO: Use the ViewModel
//for (int j=0; j< dataLoggerList.length; j++){ DummyArrayList.add(dataLoggerList[j]);}
RecyclerView recyclerView = getView().findViewById(R.id.config_datalogger_recycle_view);
ConfigDataloggerAdapter configDataloggerAdapter = new ConfigDataloggerAdapter(dataLoggerList, getActivity());
recyclerView.setAdapter(configDataloggerAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
I have list of EditText in my fragment and I am setting those EditText in the adapter and I am also saving the values from EditTexts into an Array which is defined in Adapter itself.
public class ConfigDataloggerAdapter extends RecyclerView.Adapter<ConfigDataloggerAdapter.ViewHolder>{
//private ArrayList<RFIDReader> readers = new ArrayList<>();
private String [] mDummyList ;
// private ArrayList<String> mDummyArrayList = new ArrayList<>();
public String [] mDummyArrayList;
//public ArrayList<String> mConfigDataloggerData ;
public String[] mConfigDataloggerData;
// private ConfigDataloggerViewModel mConfigDataModel;
public Map<String, String> tempDataModel = new HashMap<>();
private Context mContext;
public ConfigDataloggerAdapter( String [] mDummyArrayList, Context mContext) {
this.mDummyArrayList = mDummyArrayList;
this.mContext = mContext;
mConfigDataloggerData = new String[mDummyArrayList.length];
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.config_datalogger_list,viewGroup,false);
ConfigDataloggerAdapter.ViewHolder holder = new ConfigDataloggerAdapter.ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ConfigDataloggerAdapter.ViewHolder holder, int i) {
String [] mConfigDataloggerText = null;
// for (int j=0; j< mDummyList.length; j++){ mDummyArrayList.add(mDummyList[j]);}
//ReaderDevice readerDevice = mDummyArrayList.get(i);
String temp = mDummyArrayList[i];
holder.mConfigDataloggerListText.setText(temp);
// tempDataModel.put(temp,mConfigDataloggerData.get(i) );
// mConfigDataModel.setConfigDataloggerVMData(tempDataModel);
//holder.reader_checkedTextView.setText(readerDevice.getName() );
}
#Override
public int getItemCount() {
return mDummyArrayList.length;
}
public class ViewHolder extends RecyclerView.ViewHolder{
public TextView mConfigDataloggerListText;
public EditText mConfigDataloggarListEditText;
public LinearLayout configDataloggerLayout;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mConfigDataloggerListText = itemView.findViewById(R.id.textView_config_datalogger);
mConfigDataloggarListEditText = itemView.findViewById(R.id.editText_config_datalogger);
mConfigDataloggarListEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mConfigDataloggerData[getAdapterPosition()] =
mConfigDataloggarListEditText.getText().toString();
//here I am storing data from editText to the array
}
#Override
public void afterTextChanged(Editable s) {
}
});
configDataloggerLayout = itemView.findViewById(R.id.config_datalogger_list_layout);
}
}
}
I have two questions, 1) how to access mConfigDataloggerData from adapter in the Fragment? 2) I have a button in same fragment. when I press the button, other fragment starts. Now, I want to save data from mConfigDataloggerData to ViewModel when press the button. So where exactly I write mViewModel = ViewModelProviders.of(this).get(xxxx.class); ?
For your reference, below code is of an activity where my Fragments are attached.
public class defaultActivity extends AppCompatActivity {
private String TAG = "default activity";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.datalogger_activity);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ConfigDataloggerFragment configDataloggerFragment = new ConfigDataloggerFragment();
// getSupportFragmentManager().beginTransaction().add(R.id.default_datalogger_activity, datalogger).commit();
getSupportFragmentManager().beginTransaction().add(R.id.default_datalogger_activity, configDataloggerFragment).commit();
}
public void StartorStopInventory(View view) {
Button button = (Button) view;
if (application.mConnectedReader.isConnected()){
if (application.mIsInventoryRunning ){
application.mIsInventoryRunning = true;
button.setText("STOP");
try{
TriggerInfo triggerInfo = new TriggerInfo();
Log.d(TAG, "Start trigger setting when button is pressed" + triggerInfo.StartTrigger.getTriggerType());
Log.d(TAG, "Stop trigger setting when button is pressed" + triggerInfo.StartTrigger.getTriggerType());
application.mConnectedReader.Actions.Inventory.perform();
}catch (InvalidUsageException e){
Log.d(TAG, "StartorStopInventory: Inventory perform fail " + e);
} catch (final OperationFailureException op) {
op.printStackTrace();
Log.d(TAG, "StartorStopInventory: Operational failure " + op.getResults() + " " + op.getVendorMessage());
Toast.makeText(view.getContext(), op.getVendorMessage(), Toast.LENGTH_LONG);
}
}
}
}
public void start_data_logging_click(View view) {
Datalogger datalogger = new Datalogger();
// getSupportFragmentManager().beginTransaction().replace(R.id.default_datalogger_activity, datalogger);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.default_datalogger_activity, datalogger);
transaction.addToBackStack(null);
transaction.commit();
}
}
1) Create getters in Adapter for your fields, ex
public String[] getConfigDataloggerData(){
return mConfigDataloggerData;
}
...
To declare adapter globally;
public class YourFragment {
ConfigDataloggerAdapter configDataloggerAdapter,
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(ConfigDataloggerViewModel.class);
dataLoggerList = getResources().getStringArray(R.array.DataLoggerStringArray);
// TODO: Use the ViewModel
//for (int j=0; j< dataLoggerList.length; j++){ DummyArrayList.add(dataLoggerList[j]);}
RecyclerView recyclerView = getView().findViewById(R.id.config_datalogger_recycle_view);
configDataloggerAdapter = new ConfigDataloggerAdapter(dataLoggerList, getActivity());
recyclerView.setAdapter(configDataloggerAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
}
}
Then inside your Fragment, call configDataloggerAdapter.getConfigDataloggerData() and you will get your data. Same for other fields
2) I dont yet understand that part
I have a recyclerView with a list of Competitor objects. The list that populates the RecyclerView is a global Singleton. In that Singleton's constructor I open a Json file, parse it's contents to populate the global Singleton's list of Competitors and use that list to pass to the RecyclerView's adapter. Each list item has an ImageButton. This is what I'm trying to accomplish;
When the user clicks on the ImageButton (Delete Button) I want an AlertDialog to pop up and ask the user if they are sure they want to delete the Competitor. This part I have so far. But what I need to do next I can't figure out. I am able to update the json file that contains the global list's information but I also want to update the recyclerview by removing the Competitor from the RecyclerView by calling:
mCompetitorsList.remove(competitor); notifyItemRemoved(position);
However I can't get a reference to the mCompetitorsList variable from an external Dialog class. The same goes for calling notifiyItemRemoved(position)
What should I do? Below is the code for my Dialog class, my Activity that contains the RecyclerView and it's Adapter as well as the Singleton implementation.
public class MasterCompetitorsListActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
private static final String DIALOG_DELETE_COMPETITOR = "DIALOG_DELETE_COMPETITOR";
private RecyclerView mRecyclerView;
private List<Competitor> mCompetitorsList;
private CompetitorListAdapter mAdapter;
private SearchView mSearchView;
private FloatingActionButton mAddCompetitorButton;
private Button mDeletCompetitor;
private TextView mCompetitorHidden;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_master_competitors_list);
mSearchView = (SearchView) findViewById(R.id.searchView);
mSearchView.setOnQueryTextListener(this);
/* initialize the Global Competitor's List for the recyclerview. Because this is a singleton
it should initialize the list for the entire app's runtime
*/
GlobalCompetitorsList.get();
mCompetitorsList = GlobalCompetitorsList.getCompetitors();
mRecyclerView = (RecyclerView) findViewById(R.id.master_competitors_recycler);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
mAdapter = new CompetitorListAdapter(this, mCompetitorsList);
mRecyclerView.setAdapter(mAdapter);
// set a separator for the list items
DividerItemDecoration divider = new DividerItemDecoration(
mRecyclerView.getContext(),
layoutManager.getOrientation());
divider.setDrawable(ContextCompat.getDrawable(MasterCompetitorsListActivity.this, R.drawable.divider_dark));
mRecyclerView.addItemDecoration(divider);
mRecyclerView.setAdapter(mAdapter);
mAddCompetitorButton = (FloatingActionButton) findViewById(R.id.add_master_competitor_floating_button);
mAddCompetitorButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MasterCompetitorsListActivity.this, AddNewMasterCompetitorActivity.class);
startActivity(intent);
}
});
}
#Override
public boolean onQueryTextSubmit(String query) {
mCompetitorsList = new ArrayList<>();
mCompetitorsList = GlobalCompetitorsList.getCompetitors();
mAdapter.notifyDataSetChanged();
return false;
}
#Override
public boolean onQueryTextChange(String query) {
mCompetitorsList = GlobalCompetitorsList.getCompetitors();
query = query.toLowerCase();
final List<Competitor> filteredList = new ArrayList<>();
for (int i = 0; i < mCompetitorsList.size(); i++) {
final String lastName = mCompetitorsList.get(i).getLastName().toLowerCase();
final String firstName = mCompetitorsList.get(i).getFirstName().toLowerCase();
if (lastName.contains(query) || firstName.contains(query)) {
filteredList.add(mCompetitorsList.get(i));
}
}
mAdapter.setFilter(filteredList);
return true;
}
// ********* RecyclerView Adapter class *************************************************************************
public class CompetitorListAdapter extends RecyclerView.Adapter<CompetitorListAdapter.CompetitorViewHolder> {
List<Competitor> mCompetitors;
Context mContext;
public CompetitorListAdapter(Context context, List<Competitor> competitors) {
mContext = context;
mCompetitors = competitors;
}
#Override
public CompetitorListAdapter.CompetitorViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(MasterCompetitorsListActivity.this);
View itemView = inflater.inflate(R.layout.list_item_master_competitor, parent, false);
CompetitorViewHolder viewHolder = new CompetitorViewHolder(itemView);
return viewHolder;
}
#Override
public void onBindViewHolder(CompetitorListAdapter.CompetitorViewHolder holder, final int position) {
final Competitor competitor = mCompetitorsList.get(position);
try {
holder.firstName.setText(competitor.getFirstName());
holder.lastName.setText(competitor.getLastName());
holder.memberNum.setText(competitor.getMemberNum());
holder.deleteCompetitor.setImageResource(R.drawable.ic_delete_forever_white_24dp);
holder.container.findViewById(R.id.main_container);
holder.hiddenCompetitorId.setText(competitor.getCompetitorId().toString());
} catch (Exception e) {
e.printStackTrace();
}
holder.deleteCompetitor.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fragmentManager = getSupportFragmentManager();
DeleteCompetitorDialogFragment dialog = new DeleteCompetitorDialogFragment();
dialog.show(fragmentManager, DIALOG_DELETE_COMPETITOR);
// mCompetitorsList.remove(competitor); // remove from the global singleton list
// notifyItemRemoved(position);
}
});
}
#Override
public int getItemCount() {
return mCompetitorsList.size();
}
// ************* View Holder Class **************************************************************************
public class CompetitorViewHolder extends RecyclerView.ViewHolder {
public TextView firstName;
public TextView lastName;
public TextView memberNum;
public ImageButton deleteCompetitor;
public ConstraintLayout container;
public TextView hiddenCompetitorId;
boolean comptitorIsActive = false;
public CompetitorViewHolder(final View itemView) {
super(itemView);
firstName = (TextView) itemView.findViewById(R.id.first_name);
lastName = (TextView) itemView.findViewById(R.id.last_name);
deleteCompetitor = (ImageButton) itemView.findViewById(R.id.delete_competitor_button);
hiddenCompetitorId = (TextView) itemView.findViewById(R.id.competitor_id_hidden);
container = (ConstraintLayout) itemView.findViewById(R.id.main_container);
memberNum = (TextView) itemView.findViewById(R.id.member_num);
}
}
// ************ End of View Holder Class ********************************************************************
public void setFilter(List<Competitor> newList) {
mCompetitorsList = new ArrayList<>();
mCompetitorsList.addAll(newList);
notifyDataSetChanged();
}
}
// ************* End of RecyclerView Adapter class **********************************************************
}
Here is the Dialog class:
public class DeleteCompetitorDialogFragment extends DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState){
final GlobalCompetitorsList mCompetitorsList = GlobalCompetitorsList.get();
return new AlertDialog.Builder(getActivity())
.setTitle("Delete this Competitor?")
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
// remove from the master_competitors.json file by overwriting the original file with the new
// global list
File file = new File("data/data/com.checkinsystems.ez_score/files/master_competitors.json");
if (file.exists()) {
FileOutputStream fos = null;
try {
String jsonString = new Gson().toJson(mCompetitorsList);
fos = getActivity().openFileOutput("master_competitors.json", getActivity().MODE_PRIVATE);
fos.write(jsonString.getBytes());
// somehow access the list from the calling activity to remove the item
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
assert fos != null;
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
})
.create();
}
}
And if it helps to understand my code, here is the Singleton class
public class GlobalCompetitorsList {
public static GlobalCompetitorsList sGlobalCompetitorsList;
public static List<Competitor> sCompetitors;
public static GlobalCompetitorsList get() {
if(sGlobalCompetitorsList == null){
return new GlobalCompetitorsList();
} else {
return sGlobalCompetitorsList;
}
}
private GlobalCompetitorsList() {
File file = new File("data/data/com.checkinsystems.ez_score/files/master_competitors.json");
String jsonString;
if(file.exists()){
BufferedReader reader = null;
List<Competitor> list;
sCompetitors = new ArrayList<>();
try {
reader = new BufferedReader(new FileReader(file));
jsonString = reader.readLine();
Type compType = new TypeToken<List<Competitor>>(){}.getType();
list = new Gson().fromJson(jsonString, compType);
addCompetitors(list);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
assert reader != null;
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
sCompetitors = new ArrayList<>();
}
}
public void addCompetitor(Competitor c){
sCompetitors.add(c);
}
public static void addCompetitors(List<Competitor> c){
sCompetitors.addAll(c);
}
public static List<Competitor> getCompetitors(){
return sCompetitors;
}
}
Simple just create a constructor for the Dialog that you are using
public DeleteCompetitorDialogFragment(IMyListenerCallback listener){
mListener = listener;
}
later on//
if(listener != null){
listener.doWhatYouNeed(stuffToPass);
}
Then make an interface class
public interface IMyListenerCallback{
void doWhatYouNeed(Object stuffToPass);
}
//then in your calling activity
public class MainActivity extends AppCompatActivity implements IMyListenerCallback{
private void launchDialog(){
new DeleteCompetitorDialogFragment(this).show();
}
#Override
public void doWhatYouNeed(Object stuffToPass){
}
}
Of course this is pseduo code and not tested, but hopefully you get the picture. Goodluck.
I am working on an ecom app wich includes the cart management. Now i have a fragment(CartFragment) and an adapter(ShowCartAdapter)attached to recyclerView.
I have made three network calls in a single fragment(i.e 1. add item to cart,2. show item in cart,3. delete item from cart).
The above fragment is attached to an activity(ProductDetailActivity).Adding item to cart and show item in cart is working perfect but the third one i.e remove item from cart is troubling me.I have an icon in my cardview to remove an item,on click of which i want to delete that item from recyclerview,now i am sending an unique id of item from adapter to fragment but it is giving me null pointer on ProgressDialog(progressDialog=new ProgressDialog(getActivity());) when i click on that icon.Might be the activity is no more attached to that fragment. Below is my code snippet for adapter,fragment and activity.Please help me !!!
CartFragment
public class CartFragment extends Fragment implements RetrofitTaskListener<AddCart> {
private ProgressDialog progressDialog;
private RecyclerView recyclerView;
private AdapterAddCart adapter;
private AdapterShowCart adapterShowCart;
private boolean loading = true;
AddCart addCartList;
int pageIndex;
private LinearLayoutManager linearLayoutManager;
private String email1,articlCode,image,quantity,cost;
private static final String STARTING_TEXT = "Four Buttons Bottom Navigation";
private Button btnCheckout;
private FragmentTransaction fragmentTransaction;
private int frag,cartSize;
private TextView cartEmptyTxt;
private Context context;
private SharedPreferences sharedPreference;
private SharedPreferences.Editor editor;
private SessionManager session;
private EditText cmntTxt;
public CartFragment() {
// Required empty public constructor
}
public static CartFragment newInstance(int text) {
Bundle args = new Bundle();
args.putInt(STARTING_TEXT, text);
CartFragment sampleFragment = new CartFragment();
sampleFragment.setArguments(args);
return sampleFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
articlCode = getArguments().getString("artCode");
image = getArguments().getString("image");
quantity = getArguments().getString("quantity");
cost = getArguments().getString("cost");
frag = getArguments().getInt("fragment");
View view = inflater.inflate(R.layout.fragment_cart, container, false);
cmntTxt = (EditText)view.findViewById(R.id.comment_txt);
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
session = new SessionManager(getActivity().getApplicationContext());
sharedPreference = getActivity().getSharedPreferences("CART",0);
editor = sharedPreference.edit();
((AppCompatActivity) getActivity()).getSupportActionBar().setTitle("Cart");
btnCheckout = (Button)view.findViewById(R.id.btnCheckout);
cartEmptyTxt = (TextView)view.findViewById(R.id.emptytxt);
cartEmptyTxt.setVisibility(View.GONE);
if (!session.isLoggedIn()) {
cartEmptyTxt.setVisibility(View.VISIBLE);
btnCheckout.setVisibility(View.GONE);
cmntTxt.setVisibility(View.GONE);
}
btnCheckout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FragmentManager fm = getFragmentManager();
fragmentTransaction = fm.beginTransaction();
AddressFragment addressFragment = new AddressFragment();
fragmentTransaction.replace(R.id.fragmentContainer,addressFragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit(); }
});
pageIndex = 0;
recyclerView = (RecyclerView)view.findViewById(R.id.cart_recycler_view);
linearLayoutManager=new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
SQLiteHandler sqLiteHandler = new SQLiteHandler(getActivity());
List<SessionModel> sessionModelList = sqLiteHandler.getUserDetails();
Bundle arguments = getArguments();
if (arguments != null) {
for (SessionModel sm : sessionModelList){
email1 = sm.getEmail();
}
if (frag == 6){
callCartService(email1,articlCode,cost,quantity);
}else if (email1!=null){
callGetCart(email1);
}
}
return view;
}
public void callCartService(String email,String artCode,String price,String qty){
showProgreass();
pageIndex = pageIndex + 1;
String url = String.format(ServerConfigStage.ADD_CART(),email,artCode,price,qty);
RetrofitTask task = new RetrofitTask<>(CartFragment.this, CommonUtility.HTTP_REQUEST_TYPE.POST, CommonUtility.CallerFunction.ADD_CART_FUNCTION, url,getActivity());
task.execute();
}
public void callGetCart(String email){
showProgreass();
pageIndex = pageIndex + 1;
String url = String.format(ServerConfigStage.GET_CART(),email);
RetrofitTask task = new RetrofitTask<>(CartFragment.this, CommonUtility.HTTP_REQUEST_TYPE.POST, CommonUtility.CallerFunction.GET_CART, url,getActivity());
task.execute();
}
public void delItemCart(String email,String itemId){
adapterShowCart = new AdapterShowCart(getContext(),CartFragment.this);
showProgreass();
String url = String.format(ServerConfigStage.DEL_ITEM_CART(),email,itemId);
RetrofitTask task = new RetrofitTask<>(CartFragment.this, CommonUtility.HTTP_REQUEST_TYPE.POST, CommonUtility.CallerFunction.DEL_ITEM_CART, url,getActivity());
task.execute();
}
public void showProgreass(){
progressDialog=new ProgressDialog(getActivity());
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Please Wait...");
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
progressDialog.show();
}
public void stopProgress(){
if(progressDialog!=null && progressDialog.isShowing())
progressDialog.cancel();
}
#Override
public void onRetrofitTaskComplete(Response<AddCart> response, Context context, CommonUtility.CallerFunction _callerFunction) {
stopProgress();
if (response.isSuccess()) {
if (response.body() != null) {
addCartList =response.body();
if (_callerFunction == CommonUtility.CallerFunction.ADD_CART_FUNCTION){
if (addCartList.getStatus() == 0){
cartSize = addCartList.getDeatils().size();
editor.putInt("CART_ITEMS",cartSize);
editor.commit();
Toast.makeText(context, addCartList.getResponse(), Toast.LENGTH_SHORT).show();
if (adapter == null) {
adapter = new AdapterAddCart(context, R.layout.row_cart, addCartList);
recyclerView.setAdapter(adapter);
}
}else
if(addCartList.getStatus()>0) {
cartSize = addCartList.getDeatils().size();
editor.putInt("CART_ITEMS",cartSize);
editor.commit();
if (adapter == null) {
adapter = new AdapterAddCart(context, R.layout.row_cart, addCartList);
recyclerView.setAdapter(adapter);
}
adapter.notifyDataSetChanged();
}else {cartSize = addCartList.getDeatils().size();
editor.putInt("CART_ITEMS",cartSize);
editor.commit();
if (adapter == null) {
adapter = new AdapterAddCart(context, R.layout.row_cart, addCartList);
recyclerView.setAdapter( adapter );;
}
adapter.notifyDataSetChanged();
Toast.makeText(context, addCartList.getResponse(), Toast.LENGTH_SHORT).show();
}
}else if (_callerFunction == CommonUtility.CallerFunction.GET_CART){
if (addCartList.getStatus() == 0){
if (addCartList.getCart().size()>0){
cartSize = addCartList.getCart().size();
editor.putInt("CART_ITEMS",cartSize);
editor.commit();
}
}else
if(addCartList.getStatus()>0) {
if (addCartList.getCart().size()>0){
cartSize = addCartList.getCart().size();
editor.putInt("CART_ITEMS",cartSize);
editor.commit();}
if (adapterShowCart == null) {
adapterShowCart = new AdapterShowCart(context, R.layout.row_cart, addCartList);
recyclerView.setAdapter(adapterShowCart);
;
}
adapterShowCart.notifyDataSetChanged();
}else {
cartEmptyTxt.setVisibility(View.VISIBLE);
}
//Toast.makeText(context, addCartList.getResponse(), Toast.LENGTH_SHORT).show();
}else if (_callerFunction == CommonUtility.CallerFunction.DEL_ITEM_CART){
if (addCartList.getStatus()>0){
if (adapterShowCart == null) {
adapterShowCart = new AdapterShowCart(context, R.layout.row_cart, addCartList);
recyclerView.setAdapter(adapterShowCart);
}adapterShowCart.notifyDataSetChanged();
}
}
}
}
}
#Override
public void onRetrofitTaskFailure(Throwable t) {
stopProgress();
// Toast.makeText(getActivity(),"Fail to load Data",Toast.LENGTH_LONG).show();
if (getActivity()!= null)
{
getActivity().finish();
}
}
public void myFragmentMethod(){
// make sure to double check casts (to YourActivity) like these before invoking
((ProductDetailActivity)getActivity()).myOnResume();
}
}
AdapterShowCart
public class AdapterShowCart extends RecyclerView.Adapter<AdapterShowCart.ViewHolder>{
private AddCart addCartList;
private RemoveItemCommunication removeItemCommunication;
private CartFragment cartFragment = new CartFragment();
Context context;
private int layoutResourceId,cart;
private SharedPreferences sharedPreferences;
public AdapterShowCart(Context context, int layoutResourceId, AddCart addCarts) {
this.context = context;
this.layoutResourceId = layoutResourceId;
this.addCartList = addCarts;
}
public AdapterShowCart(Context context, CartFragment cartFragment) {
this.context = context;
this.cartFragment=cartFragment;
}
public void setOnClickListener(RemoveItemCommunication removeItemCommunication1){
removeItemCommunication = removeItemCommunication1;
}
#Override
public AdapterShowCart.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_cart, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(AdapterShowCart.ViewHolder viewHolder, int i) {
viewHolder.tv_android.setText("Price :"+" "+addCartList.getCart().get(i).getPrice());
viewHolder.tv_art_number.setText("Article No. :"+" "+addCartList.getCart().get(i).getItemCode());
viewHolder.tvQty.setText("Quantity :"+""+addCartList.getCart().get(i).getCartQuantity());
//viewHolder.img_android.setImageResource(products.get(i).getAndroid_image_url());
Picasso.with(context).load(addCartList.getCart().get(i).getURL()).resize(240, 120).into(viewHolder.img_android);
}
#Override
public int getItemCount() {
// cart = sharedPreferences.getInt("CART_ITEMS",0);
return addCartList.getCart().size();
}
class ViewHolder extends RecyclerView.ViewHolder{
private TextView tv_android,tv_art_number,tvQty;
private ImageView img_android,remove;
private int pos;
private CardView cardView;
public ViewHolder(View view) {
super(view);
tv_android = (TextView)view.findViewById(R.id.tvTitle);
tv_art_number=(TextView)view.findViewById(R.id.tvNumber);
cardView = (CardView)view.findViewById(R.id.card_view);
img_android = (ImageView) view.findViewById(R.id.mealImage);
tvQty=(TextView)view.findViewById(R.id.tvQty);
remove=(ImageView)view.findViewById(R.id.removeItem);
remove.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int pos = getAdapterPosition();
cartFragment.delItemCart(addCartList.getEmail(),addCartList.getCart().get(pos).getId());
}
});
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
pos = getAdapterPosition();
}
});
}
}
}
ProductDetailActivity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_detail);
this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
toolbar = (Toolbar) findViewById(R.id.tool_bar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setTitle("Product Details");
supportInvalidateOptionsMenu();
toolbar.setTitleTextColor(Color.WHITE);
session = new SessionManager(getApplicationContext());
itemCode = getIntent().getExtras().getString("ItemCode");
itemName = getIntent().getExtras().getString("ItemName");
stockAvailibility = (ImageView) findViewById(R.id.stock_image);
code = (TextView) findViewById(R.id.item_code);
price = (TextView) findViewById(R.id.price_txt);
name = (TextView) findViewById(R.id.product_name);
productImage = (ImageView) findViewById(R.id.image_big);
stock = (TextView) findViewById(R.id.stock);
stock_status = (TextView) findViewById(R.id.stock_text);
quantity_txt = (EditText) findViewById(R.id.unit_number);
qtyText = (TextView) findViewById(R.id.selectQty);
addCart = (Button) findViewById(R.id.btn_add_cart);
callProductDetail(itemCode);
addCart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String selectedQty = quantity_txt.getText().toString();
if (session.isLoggedIn()) {
if (!selectedQty.isEmpty() && Integer.parseInt(selectedQty) > Integer.parseInt(qty)) {
AlertDialog.Builder builder = new AlertDialog.Builder(ProductDetailActivity.this);
builder.setMessage("You can not add more than" + " " + qty + " " + "units")
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//do things
}
});
AlertDialog alert = builder.create();
alert.show();
} else if (selectedQty.isEmpty() || Integer.parseInt(selectedQty) == 0) {
AlertDialog.Builder builder = new AlertDialog.Builder(ProductDetailActivity.this);
builder.setMessage("Please Add Quantity")
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//do things
}
});
AlertDialog alert = builder.create();
alert.show();
} else if (!selectedQty.isEmpty() && Integer.parseInt(selectedQty) != 0 && Integer.parseInt(selectedQty) <= Integer.parseInt(qty)) {
addCart.setVisibility(View.GONE);
hideKeyboard(ProductDetailActivity.this);
fm = getSupportFragmentManager();
fragmentTransaction = fm.beginTransaction();
CartFragment cartFragment = new CartFragment();
fragmentTransaction.replace(R.id.fragmentContainer,cartFragment);
Bundle bundle = new Bundle();
bundle.putString("artCode", artCode);
bundle.putString("image",image_url);
bundle.putString("quantity",selectedQty);
bundle.putString("cost",cost);
bundle.putInt("fragment",6);
cartFragment.setArguments(bundle);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commitAllowingStateLoss();
}
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(ProductDetailActivity.this);
builder.setMessage("Please Login To Continue")
.setCancelable(false)
.setNegativeButton("NOT NOW", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.setPositiveButton("LOGIN", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Intent intent = new Intent(ProductDetailActivity.this, LoginActivity.class);
intent.putExtra("fragment", 7);
startActivity(intent);
}
});
AlertDialog alert = builder.create();
alert.show();
}
}
});
}
public void myOnResume(){
this.onResume();
addCart.setVisibility(View.VISIBLE);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
// todo: goto back activity from here
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void showProgreass() {
progressDialog = new ProgressDialog(ProductDetailActivity.this);
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Please Wait...");
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
progressDialog.show();
}
public void stopProgress() {
if (progressDialog != null && progressDialog.isShowing())
progressDialog.cancel();
}
public void callProductDetail(String productId) {
showProgreass();
String url = String.format(ServerConfigStage.GET_PRODUCT_DETAIL(), productId);
RetrofitTask task = new RetrofitTask<List<ProductDetail>>(ProductDetailActivity.this, CommonUtility.HTTP_REQUEST_TYPE.GET, CommonUtility.CallerFunction.GET_PRODUCT_DETAIL, url, ProductDetailActivity.this);
task.execute();
}
#Override
public void onRetrofitTaskComplete(Response<List<ProductDetail>> response, Context context, CommonUtility.CallerFunction _callerFunction) {
stopProgress();
if (response.isSuccess()) {
if (response.body() != null) {
if (response.body().get(0).getStatus() > 0) {
String json = gson.toJson(response);
System.out.println(json);
artCode = response.body().get(0).getItemcode();
cost = response.body().get(0).getPrice();
String desc = response.body().get(0).getDescription();
image_url = response.body().get(0).getURL();
Double d = response.body().get(0).getStock();
Double aDouble = new Double(d);
int i = aDouble.intValue();
qty = String.valueOf(i);
if (qty.equals("0")) {
stock_status.setText("Not In Stock");
stockAvailibility.setImageResource(R.mipmap.stockunavailable);
quantity_txt.setVisibility(View.GONE);
qtyText.setVisibility(View.GONE);
addCart.setVisibility(View.GONE);
} else {
stockAvailibility.setImageResource(R.mipmap.stock_image);
}
code.setText(artCode);
price.setText("Euro" + "" + cost);
productDescription = (ExpandableTextView) findViewById(R.id.expand_text_view);
productDescription.setText(desc);
name.setText(itemName);
stock.setText("Units :" + " " + qty);
Picasso.with(context).load(image_url).resize(240, 120).into(productImage);
} else {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(response.body().get(0).getResponse())
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//do things
}
});
AlertDialog alert = builder.create();
alert.show();
//Toast.makeText(context, response.body().get(0).getResponse(), Toast.LENGTH_SHORT).show();
}
}
}
}
#Override
public void onRetrofitTaskFailure(Throwable t) {
stopProgress();
//Toast.makeText(ProductDetailActivity.this,"Fail to load Data",Toast.LENGTH_LONG).show();
finish();
}
public static void hideKeyboard(Context ctx) {
InputMethodManager inputManager = (InputMethodManager) ctx
.getSystemService(Context.INPUT_METHOD_SERVICE);
// check if no view has focus:
View v = ((Activity) ctx).getCurrentFocus();
if (v == null)
return;
inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
StackTrace
Process: com.jbm.jbmcustomer, PID: 9188
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources$Theme android.content.Context.getTheme()' on a null object reference
at android.app.AlertDialog.resolveDialogTheme(AlertDialog.java:222)
at android.app.AlertDialog.<init>(AlertDialog.java:200)
at android.app.AlertDialog.<init>(AlertDialog.java:196)
at android.app.AlertDialog.<init>(AlertDialog.java:141)
at android.app.ProgressDialog.<init>(ProgressDialog.java:77)
at com.jbm.jbmcustomer.fragment.CartFragment.showProgreass(CartFragment.java:179)
at com.jbm.jbmcustomer.fragment.CartFragment.delItemCart(CartFragment.java:172)
at com.jbm.jbmcustomer.adapter.AdapterShowCart$1.onClick(AdapterShowCart.java:80)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
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)
The reason for getActivity returning null is, you are using an instance of cart fragment which was initialized inside the adapter class which was not attached to any activity.
So please pass an instance of CartFragment from CartFragment to the adapter class to resolve the issue. There is a constructor in AdapterShowCart class in which the cart fragment instance is passed but it is called inside delItemCart(String email,String itemId) in fragment (I didn't understand why its done like that).
In AdapterShowCart line 80 you are triggering an action, which tries to get a value from resources using a reference to a Context which doesn't exist anymore.
Presumably, ProductDetailActivity.this causes the issues.
I'm using recyclerview to show my list of ground machines. Also I have a check box widget. When check box is checked, I want to sort my list by brand of machine. In my adapter I have a method setMachine(List listMachines); which has a reference to my current list of machines. Also my sort method works fine, but when I checked my check box my list is not sorted, worst it's disappeared, and my current list of machines is zero. Can someone help me to understand why that is happening:
My RecyclerView Adapter:
public class ListMachineAdapter extends RecyclerView.Adapter<ListMachineAdapter.ViewHolder> {
private List<Machine> listOfMachines;
private ClickMachineItemListener selectMachine;
private View.OnClickListener showToast = new View.OnClickListener() {
#Override
public void onClick(View v) {
ViewHolder vh = (ViewHolder) v.getTag();
int position = vh.getItemPosition();
selectMachine.onClick(position);
}
};
public ListMachineAdapter(List<Machine> listOfMachines) {
this.listOfMachines = listOfMachines;
}
#Override
public ListMachineAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_list_machine, parent, false);
view.setOnClickListener(showToast);
return new ViewHolder(view, viewType);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Machine machine = listOfMachines.get(position);
holder.setPosition(position);
holder.brandMachine.setText(machine.getTypeBrand());
holder.typeMachine.setText(machine.getTypeMachine());
}
#Override
public int getItemCount() {
return listOfMachines.size();
}
public void setMachine(List<Machine> listMachines){
this.listOfMachines = listMachines; // size = 0 ??
}
public void setSelectMachine(ClickMachineItemListener selectMachine){
this.selectMachine = selectMachine;
}
Also I using Singleton to store my sort method:
public class MachineManager {
private static MachineManager instance;
private List<Machine> listOfGroundMachines;
private MachineManager() {
listOfGroundMachines = new ArrayList<>();
}
public static MachineManager getInstance() {
return instance = (instance == null) ? new MachineManager() : instance;
}
public List<Machine> sortByTypeBrand() {
Collections.sort(listOfGroundMachines, new Comparator<Machine>() {
#Override
public int compare(Machine lhs, Machine rhs) {
return lhs.getTypeBrand().compareToIgnoreCase(rhs.getTypeBrand());
}
});
return listOfGroundMachines;
}
}
And this is my Activity:
public class ListGroundMachineActivity extends Activity {
private CheckBox sortByTypeMachine, sortByTypeEngine, sortByTypeBrand, sortByYear;
private List<Machine> listOfGroundMachines;
private ListMachineAdapter adapter;
private MachineManager manager;
private ClickMachineItemListener click = new ClickMachineItemListener() {
#Override
public void onClick(int position) {
Machine machine = listOfGroundMachines.get(position);
Intent intent = new Intent(ListGroundMachineActivity.this, MachineDetailsActivity.class);
intent.putExtra(Constants.TYPE, machine.getTypeMachine());
intent.putExtra(Constants.BRAND, machine.getTypeBrand());
intent.putExtra(Constants.YEAR, machine.getYear());
intent.putExtra(Constants.ENGINE, machine.getTypeEngine());
Toast.makeText(ListGroundMachineActivity.this, machine.getTypeBrand(), Toast.LENGTH_SHORT).show();
startActivity(intent);
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_ground_machine);
manager = MachineManager.getInstance();
listOfGroundMachines = populateGroundListMachine();
Log.i("TAG", "List size is " + listOfGroundMachines.size());
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.list_ground_machine);
adapter = new ListMachineAdapter(listOfGroundMachines);
sortByTypeMachine = (CheckBox) findViewById(R.id.sort_by_type_ground_machine);
adapter.setSelectMachine(click);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this)
.color(R.color.teal).build());
recyclerView.setAdapter(adapter);
sortByTypeMachine.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
adapter.setMachine(manager.sortByTypeBrand());
adapter.notifyDataSetChanged();
Log.i("TAG 1", "List size is " + manager.sortByTypeBrand());
}
});
}
private List<Machine> populateGroundListMachine() {
List<Machine> listOfGroundMachineOne = new ArrayList<>();
MachineDB machineDb = new MachineDB(this);
SQLiteDatabase sqLiteDatabase = machineDb.getReadableDatabase();
Cursor cursor = sqLiteDatabase.query(MachineDB.TABLE_GROUND_MACHINE, null, null, null, null, null, null);
while (cursor.moveToNext()) {
String typeBrand = cursor.getString(cursor.getColumnIndex(Constants.BRAND));
String typeMachine = cursor.getString(cursor.getColumnIndex(Constants.TYPE));
String typeEngine = cursor.getString(cursor.getColumnIndex(Constants.ENGINE));
String year = cursor.getString(cursor.getColumnIndex(Constants.YEAR));
Machine machine = new Machine(typeBrand, typeMachine, typeEngine, year);
listOfGroundMachineOne.add(machine);
}
sqLiteDatabase.close();
return listOfGroundMachineOne;
}
Your listOfGroundMachines in MachineManager is only an empty arraylist:
private MachineManager() {
listOfGroundMachines = new ArrayList<>();
}
You need to create setter for that and call the setter after this code:
manager = MachineManager.getInstance();
listOfGroundMachines = populateGroundListMachine();
// here
The MachineManager listOfGroundMachines is an empty list.
You call listOfGroundMachines = populateGroundListMachine(); in your Activity class.
The list being populated with the machines is a member of ListGroundMachineActivity and not of MachineManager.