I cant figure out whats the problem here. Im trying to add an Object "idea" from type Idea to the list ideaList. And then it throws this exception. Anyone knows?
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:404)
at java.util.AbstractList.add(AbstractList.java:425)
at smoca.ch.kreagen.Fragments.VotingFragment.(VotingFragment.java:50)
at smoca.ch.kreagen.FragmentStateHandler.chooseAndShowForVoting(FragmentStateHandler.java:69)
at smoca.ch.kreagen.Adapters.ArchiveAdapter$1.onClick(ArchiveAdapter.java:50)
at android.view.View.performClick(View.java:5155)
I want to add it after the list has been created and filled by realm-data.
right in the first constructor with Idea as param.
Class-Code:
public class VotingFragment extends Fragment implements VotingAdapter.ClickListener{
private RecyclerView recyclerView;
private VotingAdapter votingAdapter;
private Realm realm;
private List<Idea> ideaList;
private List<Vote> voteList;
private List<Owner> ownerList;
private FragmentStateHandler fragmentStateHandler;
private TextView status;
private Button startVoting;
private Button stopVoting;
public VotingFragment(Idea idea) {
getData();
ideaList.add(idea);
setStatus(true);
}
public VotingFragment() {
getData();
setStatus(false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
super.onCreateView(inflater, container, savedInstanceState);
View layout = inflater.inflate(R.layout.voting_fragment_layout, container, false);
recyclerView = (RecyclerView) layout.findViewById(R.id.votingDrawerList);
realm = Realm.getInstance(getActivity());
fragmentStateHandler = FragmentStateHandler.getInstance();
// get buttons and views
status = (TextView) layout.findViewById(R.id.statusTextView);
startVoting = (Button) layout.findViewById(R.id.startButton);
stopVoting = (Button) layout.findViewById(R.id.stopButton);
// clicklisteners for start/stop
startVoting.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setStatus(true);
// put ideas in List
// put votes in List
// put Owners in List
// sort Voting
// set timestamp (24h)
}
});
stopVoting.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setStatus(false);
// clear ideas from List
// put voting in History
}
});
votingAdapter = new VotingAdapter(getActivity(), ideaList, voteList, ownerList); // params: context, idealist, votelist, ownerlist
votingAdapter.setClickListener(this); // set clicklistener on this
recyclerView.setAdapter(votingAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return layout;
}
public void getData() {
ideaList = Collections.emptyList();
voteList = Collections.emptyList();
ownerList = Collections.emptyList();
try {
RealmQuery<Idea> ideaQuery = realm.where(Idea.class);
RealmResults<Idea> ideaQueryResult = ideaQuery.findAll();
RealmQuery<Vote> voteQuery = realm.where(Vote.class);
RealmResults<Vote> voteQueryResult = voteQuery.findAll();
RealmQuery<Owner> ownerQuery = realm.where(Owner.class);
RealmResults<Owner> ownerQueryResult = ownerQuery.findAll();
ideaList = ideaQueryResult;
voteList = voteQueryResult;
ownerList = ownerQueryResult;
} catch (Exception e) { e.printStackTrace();}
Log.d("joris", "" + ideaList);
Log.d("joris", "" + voteList);
Log.d("joris", "" + ownerList);
}
// items clicked in recyclerview
#Override
public void itemClicked(View view, int position) {
Idea current = ideaList.get(position);
fragmentStateHandler.showIdeaFrag(current);
}
public void setStatus(boolean val) {
if(val) {
status.setText("OPEN");
status.setTextColor(getResources().getColor(R.color.Green));
} else {
status.setText("CLOSED");
status.setTextColor(getResources().getColor(R.color.Red));
}
}
}
You can't modify the Lists you get back as RealmResult
Instead you probably want to copy the results of your queries to get mutable lists.
Something like
ideaList = new ArrayList<>();
voteList = Collections.emptyList();
ownerList = Collections.emptyList();
try {
RealmQuery<Idea> ideaQuery = realm.where(Idea.class);
RealmResults<Idea> ideaQueryResult = ideaQuery.findAll();
RealmQuery<Vote> voteQuery = realm.where(Vote.class);
RealmResults<Vote> voteQueryResult = voteQuery.findAll();
RealmQuery<Owner> ownerQuery = realm.where(Owner.class);
RealmResults<Owner> ownerQueryResult = ownerQuery.findAll();
ideaList.addAll(ideaQueryResult);
voteList = voteQueryResult;
ownerList = ownerQueryResult;
} catch (Exception e) { e.printStackTrace();}
As you see you can no longer use the Collections.emptyList as default value as it is immutable, and instead of using the ideaQueryResult directly we copy all the elements from the list to our own mutable ArrayList.
Related
The title might be a little confusing so I hope that I can express my problem correctly. So I'm working on a simple workout log app. I have fragment ActiveWorkout as in Image 1. When I press the pink add button I am directed to another fragment, which contains different exercises as a List, which is shown in Image 2. Then I am to select an exercise(with the onItemClickListener) and the title of that exercise should be sent back to the ActiveWorkoutFragment and added to the Active Workout, so it should be like Image 3. So the problem here is, I don't exactly know how to keep my Active Workout 'alive', it should be updated if I want to add another exercise and not be blank when I press the pink add button again, so in the end it should be something like in Image 4. I was thinking about sending data with a Bundle, which I also tried in the code but the more difficult part is updating the Workout list without deleting the previous added exercises. Btw the reason I am trying to do something like this is because the data is actually in Firebase Database, so in a sense I'm trying to retrieve data from the Workout database.
Images:
Image 1 Image 2 Image 3 Image 4
This is the Exercise List or the Catalog:
public class ExercisesFragment extends Fragment {
private ListView lv;
private FirebaseListAdapter adapter;
private ArrayList<Exercise> exerciseList;
private ArrayList<String> nameList;
//private Adapter adapter;
public ExercisesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_exercises, container, false);
lv = v.findViewById(R.id.lv);
Query query = FirebaseDatabase.getInstance().getReference().child("exerciseList");
FirebaseListOptions<ExerciseElement> options = new FirebaseListOptions.Builder<ExerciseElement>()
.setLayout(R.layout.exercise)
.setQuery(query, ExerciseElement.class)
.build();
adapter = new FirebaseListAdapter(options) {
#Override
protected void populateView(#NonNull View v, #NonNull Object model, int position) {
TextView bodypart = v.findViewById(R.id.bodypart);
TextView title = v.findViewById(R.id.title);
ExerciseElement el = (ExerciseElement) model;
bodypart.setText(el.getBodypart().toString());
title.setText(el.getTitle().toString());
}
};
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ExerciseElement el = (ExerciseElement) lv.getItemAtPosition(position);
String item = el.getTitle();
ActiveWorkoutFragment awf = new ActiveWorkoutFragment();
Bundle args = new Bundle();
args.putString("ExerciseTitle", item);
awf.setArguments(args);
getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, awf).commit();
//Navigation.findNavController(v).navigate(R.id.activeWorkoutFragment);
}
});
return v;
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
}
Then there is the ActiveWorkoutFragment, which is a little longer but the upper part is not the concern. The addNewExercise() method is being called when I click on the pink add button, so I was trying to retrieve the data somehow there.
public class ActiveWorkoutFragment extends Fragment {
private Workout workout;
private TextView emptyRecyclerView;
private RecyclerView exerciseRecyclerView;
private ExerciseRecyclerViewAdapter adapter;
private WorkoutHistory workoutHistory;
private FloatingActionButton fab;
private FirebaseAuth mAuth;
private DatabaseReference databaseWorkouts;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_active_workout, container, false);
fab = v.findViewById(R.id.fab);
fab.setOnClickListener(this::addNewExercise);
setHasOptionsMenu(true);
workout = new Workout("WORKOUT");
if(savedInstanceState != null) {
workout = savedInstanceState.getParcelable("key");
}
emptyRecyclerView = v.findViewById(R.id.empty_recycler_view);
//buildRecyclerView(workout);
exerciseRecyclerView = v.findViewById(R.id.recycler_view_exercise);
// improves performance if size of RecyclerView content is fixed
// taken from developer.android.com
exerciseRecyclerView.setHasFixedSize(true);
// use a linear layout manager for RecyclerView
LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext());
exerciseRecyclerView.setLayoutManager(layoutManager);
// add divider
RecyclerView.ItemDecoration itemDecoration = new
DividerItemDecoration(this.getContext(), DividerItemDecoration.VERTICAL);
exerciseRecyclerView.addItemDecoration(itemDecoration);
// Create adapter and set its data set to workout
adapter = new ExerciseRecyclerViewAdapter(workout, this);
// Set up swipe to dismiss and ability to move RecyclerView items around
// Create callback object for ItemTouchHelper
ItemTouchHelper.Callback callback = new CustomItemTouchHelperCallback(adapter);
// Implement object created above
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(exerciseRecyclerView);
if (adapter.getItemCount() == 0)
{
showEmptyRecyclerViewText();
}
else
{
exerciseRecyclerView.setAdapter(adapter);
}
return v;
}
// Adds save button (check mark) to action bar
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.active_workout_action_bar, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_save: {
List<Exercise> exercises = workout.getExercises();
mAuth = FirebaseAuth.getInstance();
String user_id = mAuth.getCurrentUser().getUid();
databaseWorkouts = FirebaseDatabase.getInstance().getReference("Workouts").child(user_id);
String id = databaseWorkouts.push().getKey();
workout = new Workout("abc", user_id, exercises);
databaseWorkouts.child(id).setValue(workout);
Toast.makeText(getContext(), "Workout saved", Toast.LENGTH_SHORT).show();
return true;
}
case R.id.action_delete: {
exerciseRecyclerView.requestFocus();
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Confirm deletion").setMessage("Are you sure you want to delete" +
" this workout?");
builder.setPositiveButton(android.R.string.yes, (dialog, which) -> {
try {
workoutHistory.removeWorkout(workout);
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getContext(), "Workout deleted", Toast.LENGTH_SHORT).show();
});
builder.setNegativeButton(android.R.string.no, (dialog, which) -> {
dialog.dismiss();
});
builder.show();
return true;
}
default:
// unrecognized button pressed
return super.onOptionsItemSelected(item);
}
}
public void showEmptyRecyclerViewText()
{
emptyRecyclerView.setVisibility(View.VISIBLE);
}
public void addNewExercise(View view) {
Bundle bundle = getArguments();
String value = "";
if(bundle != null) {
value = bundle.getString("ExerciseTitle");
}
System.out.println("lala");
System.out.println(value);
Exercise newExercise = new Exercise(value, -1, -1);
if (exerciseRecyclerView.getAdapter() == null) {
exerciseRecyclerView.setAdapter(adapter);
}
emptyRecyclerView.setVisibility(View.INVISIBLE);
workout.addExercise(newExercise);
adapter.notifyItemInserted(workout.getExercises().size() - 1);
}
private void hideKeyboard(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService
(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("key", workout);
}
}
Try this as a base for your project. add views to it and other necessary methods however it will provide you with the flow of module
//contract to update Framgents
public interface FragUpdater {
public void updateExerciseFrag(Exercise exercise);
}
public class ExerciseActiity extends AppCompatActivity implements FragUpdater {
FragmentManager fm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exercise_actiity);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
gotoActiveWorkoutFragment();
}
});
fm = getSupportFragmentManager();
gotoExercisesFragment();
}
private void gotoActiveWorkoutFragment() {
ActiveWorkoutFragment activeWorkoutFragment = new ActiveWorkoutFragment();
Bundle bundle = new Bundle();
activeWorkoutFragment.setArguments(bundle);
fm.beginTransaction().add(R.id.content_frame, activeWorkoutFragment, "ExerciseSelectionFrag").addToBackStack(null).commit();
}
private void gotoExercisesFragment() {
ExercisesFragment exercisesFragment = new ExercisesFragment();
Bundle bundle = new Bundle();
exercisesFragment.setArguments(bundle);
fm.beginTransaction().replace(R.id.content_frame, exercisesFragment, "ExerciseDisplayFrag").commit();
}
#Override
public void updateExerciseFrag(Exercise exercise) {
// Get Fragment ExercisesFragment
ExercisesFragment frag = (ExercisesFragment)
fm.findFragmentByTag("ExerciseDisplayFrag");
if (frag == null) {
return;
}
frag.updateList(exercise);
}
}
public class ExercisesFragment extends Fragment {
//here update your list in ExerciseFragment
public void updateList(Exercise exercise) {}
}
public class ActiveWorkoutFragment extends Fragment {
FragUpdater fragUpdater;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fragUpdater = (ExerciseActiity) getActivity();
}
private void selectListItem(Exercise exercise) {
fragUpdater.updateExerciseFrag(exercise);
getActivity().getSupportFragmentManager().popBackStack();
}
}
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 have a Navigation menu with nav menu on it. When clicked on each nav menu, the specific fragment is opened.For example, when I click on Words nav menu, words item display with recyclerView items on it. I'm fetching data from offline and external SQLite database and display on recyclerView items. Now I want to fetch data in another thread, NOT in the main thread, because I want increase loading speed data and app performance. But I don't know how to do this. please help me with a code. I read the same subject on the internet, but I still now have my issue.
this is my AllWordsFragment
public class AllWordsFragment extends Fragment {
private List<WordsList> wordsLists = new ArrayList<>();
private Cursor cursor;
ProgressBar progressBar;
RecyclerView recyclerView;
AllWordsAdapter allWordsAdapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.all_words_fragment, container, false);
progressBar = view.findViewById(R.id.progressBar);
progressBar.setMax(600);
allWordsAdapter = new AllWordsAdapter(getActivity(), wordsLists);
allWordsAdapter.notifyDataSetChanged();
recyclerView = view.findViewById(R.id.recyclerViewAllWords);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(allWordsAdapter);
loadingWords();
return view;
}
private void loadingWords() {
WordDatabase wordDatabase = new WordDatabase(getActivity());
try {
wordDatabase.createDatabase();
wordDatabase.openDatabase();
} catch (SQLiteException e) {
e.printStackTrace();
}
try {
cursor = wordDatabase.QueryData("SELECT Word, Definition, Example, WordList, ImageWord FROM Words");
if (cursor != null && cursor.moveToFirst()) {
do {
WordsList wordList = new WordsList();
wordList.setWordTitle(cursor.getString(0));
wordList.setDefinition(cursor.getString(1));
wordList.setExample(cursor.getString(2));
wordList.setVocubList(cursor.getString(3));
wordList.setImageWord(cursor.getString(4));
wordsLists.add(wordList);
} while (cursor.moveToNext());
wordDatabase.close();
}
} catch (SQLiteException w) {
w.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
}
and this is my AllWordsAdapter
public class AllWordsAdapter extends RecyclerView.Adapter {
private int lastPosition = -1;
protected Context context;
private List<WordsList> wordsListList = new ArrayList<>();
public AllWordsAdapter(Context context, List<WordsList> wordsListList) {
this.context = context;
this.wordsListList = wordsListList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.all_words_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
WordsList wordsList = wordsListList.get(position);
holder.wordTitle.setText(wordsList.getWordTitle());
holder.definitionWord.setText(Html.fromHtml(wordsList.getDefinition()));
holder.exampleWord.setText(Html.fromHtml(wordsList.getExample()));
holder.labelWordList.setLabelText(wordsList.getVocubList());
//get image from assets with Glide.
String pathImage = wordsList.getImageWord();
String assetsPath = "file:///android_asset/";
Glide.with(context)
.asBitmap()
.load(Uri.parse(assetsPath + "" + pathImage))
.into(holder.wordImage);
Log.d("path", assetsPath + "" + pathImage);
Typeface headerFont = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Bold.ttf");
holder.wordTitle.setTypeface(headerFont);
Typeface customFont = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Italic.ttf");
holder.exampleWord.setTypeface(customFont);
holder.definitionWord.setTypeface(customFont);
//cal animation function
setAnimation(holder.itemView, position);
holder.relativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, AllWordsDetails.class);
intent.putExtra("word", holder.wordTitle.getText().toString());
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return wordsListList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private CircleImageView wordImage;
private LabelTextView labelWordList;
private TextView wordTitle, definitionWord, exampleWord;
private RelativeLayout relativeLayout;
public ViewHolder(View itemView) {
super(itemView);
wordTitle = itemView.findViewById(R.id.allWordTitle);
wordImage = itemView.findViewById(R.id.circleHeaderImage);
exampleWord = itemView.findViewById(R.id.exampleAllWord);
definitionWord = itemView.findViewById(R.id.definitionAllWord);
labelWordList = itemView.findViewById(R.id.labelWordList);
relativeLayout = itemView.findViewById(R.id.relativeAllWords);
}
}
private void setAnimation(View viewToAnimation, int position) {
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition) {
ScaleAnimation scaleAnimation = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(new Random().nextInt(501));//to make duration random number between [0,501)
viewToAnimation.startAnimation(scaleAnimation);
lastPosition = position;
}
}
}
I know must be use AsyncTask and do this in background, but I don't know how do this ? Please help me with a code. Thanks .
create an AsyncTask class inside your class:
class WordLoaderTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... params) {
loadingWords();
}
protected void onPostExecute(Void param) {
allWordsAdapter.notifyDataSetChanged();
}
}//asyncClass
replace calling loadingWords() in onCreate() with this line:
new WordLoaderTask().execute();
if you (for some reason or a way of using app) start getting duplicates in your ListView, then add wordsLists.clear(); as first line inside the do{} in loadingWords() method
Try like this
public class AllWordsFragment extends Fragment {
private List<WordsList> wordsLists = new ArrayList<>();
private Cursor cursor;
ProgressBar progressBar;
RecyclerView recyclerView;
AllWordsAdapter allWordsAdapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.all_words_fragment, container, false);
progressBar = view.findViewById(R.id.progressBar);
progressBar.setMax(600);
allWordsAdapter = new AllWordsAdapter(getActivity(), wordsLists);
allWordsAdapter.notifyDataSetChanged();
recyclerView = view.findViewById(R.id.recyclerViewAllWords);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(allWordsAdapter);
loadingWords();
return view;
}
private static LoadWordsTask extends AsyncTask<Void, Void, List<WordsList>> {
private Context context;
private AllWordsAdapter adapter;
private List<WordsList> wordsLists;
public LoadWordsTask(Context context, AllWordsAdapter adapter, List<WordsList> wordsLists) {
this.context = context;
this.adapter = adapter;
this.wordsLists = wordsLists;
}
#Override
public List<WordsList> doInBackground() {
List<WordsList> data = new ArrayList<>();
WordDatabase wordDatabase = new WordDatabase(getActivity());
try {
wordDatabase.createDatabase();
wordDatabase.openDatabase();
} catch (SQLiteException e) {
e.printStackTrace();
}
try {
cursor = wordDatabase.QueryData("SELECT Word, Definition, Example, WordList, ImageWord FROM Words");
if (cursor != null && cursor.moveToFirst()) {
do {
WordsList wordList = new WordsList();
wordList.setWordTitle(cursor.getString(0));
wordList.setDefinition(cursor.getString(1));
wordList.setExample(cursor.getString(2));
wordList.setVocubList(cursor.getString(3));
wordList.setImageWord(cursor.getString(4));
data.add(wordList);
} while (cursor.moveToNext());
wordDatabase.close();
}
} catch (SQLiteException w) {
w.printStackTrace();
} finally {
if (cursor != null) {
cursor.close();
}
}
return data;
}
#Override
public void onPostExecute(List<WordsList> data) {
this.wordsLists.addAll(data);
this.adapter.notifyDataSetChanged();
}
}
}
i am having spinner with country name and below i am showing flags according to country spinner.here i want to show flag according to spinner selection and not all..how can i show that in gridView?
HERE IS MY CODE:
public class FanciersFragment extends Fragment {
private View rootView;
private Spinner spFindCountry;
private RecyclerView rvFanciers;
private ArrayList<CountryDetail> countryDetailArray;
private LinearLayout llContainer;
private String countryCode;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_fanciers, container, false);
iitializeView();
return rootView;
}
private void iitializeView() {
spFindCountry = (Spinner) rootView.findViewById(R.id.sp_country_find);
rvFanciers = (RecyclerView) rootView.findViewById(R.id.rv_fanc_items);
llContainer = (LinearLayout) rootView.findViewById(R.id.ll_fanciers_container);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity() , 3);
rvFanciers.setHasFixedSize(true);
rvFanciers.setLayoutManager(gridLayoutManager);
getCounties();
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getActivity().setTitle("FanciersResponse");
}
private void getCounties() {
if(Utility.isNetworkConnected(getActivity())) {
final Call<Countries> resp = Utility.getApiService().getContries();
resp.enqueue(new Callback<Countries>() {
#Override
public void onResponse(Call<Countries> call, Response<Countries> response) {
if (response.code() == 200) {
Countries countries = (Countries) response.body();
if (countries != null)
if (countries.getStatus() != null)
if (countries.getStatus().equals("OK")) {
countryDetailArray = (ArrayList<CountryDetail>) countries.getCountryDetails();
if(countryDetailArray != null)
populateCountrySpinner(countryDetailArray);
pupulateFanciers();
} else {
Utility.ShowSnackBar(countries.getStatusMessage() , llContainer);
}
} else {
Utility.ShowSnackBar("Network Error" , llContainer);
}
}
#Override
public void onFailure(Call<Countries> call, Throwable t) {
Utility.ShowSnackBar("No Response" , llContainer);
}
});
}
else {
Utility.ShowSnackBar(getResources().getString(R.string.no_internet), llContainer);
}
}
private void pupulateFanciers() {
Fanciers rcAdapter = new Fanciers(getActivity(), countryDetailArray , new Fanciers.OnItemClickListener() {
#Override
public void onItemClick(CountryDetail item) {
if(item != null){
Bundle b = new Bundle();
b.putSerializable(Constants.COUNTRY_DETAILS , item);
Intent intent = new Intent(getActivity() , CountryBaseFanciers.class);
intent.putExtra(Constants.BUNDLE , b);
startActivity(intent);
}
}
});
rvFanciers.setAdapter(rcAdapter);
}
private void populateCountrySpinner(final ArrayList<CountryDetail> countryDetailList) {
ArrayList<String> countryList = new ArrayList<>();
if(countryDetailList != null){
for(CountryDetail countryDetail: countryDetailList ){
countryList.add(countryDetail.getCountryName());
}
}
/*adapterCountry = new ArrayAdapter<String>(getActivity(), R.layout.spinner_layout, R.id.tv_country_name, countryList);
spCountry.setAdapter(adapterCountry);*/
HintSpinner<String> hintSpinner = new HintSpinner<>(
spFindCountry,
// Default layout - You don't need to pass in any layout id, just your hint text and
// your list data
new HintAdapter<>(getActivity(), getResources().getString(R.string.find_country), countryList),
new HintSpinner.Callback<String>() {
#Override
public void onItemSelected(int position, String itemAtPosition) {
// Here you handle the on item selected event (this skips the hint selected event)
countryCode = countryDetailList.get(position).getCountryCode();
}
});
hintSpinner.init();
}
}
I am getting all flags in gridview but i want on selection of spinner..kindly help
Instead of using GridView, try extending an ArrayAdapter class to use images, setting it in a ListView and implementing a filter based on country name. This should be fine if you want only one flag to be displayed at a time.