I have created an app that keeps track of course information. At the moment the only field that Changing dynamically is the modcode, the rest of the fields are all hardcoded to input the number 1, for now.
This is the insert code:
public boolean insertData(String ModCode,String ModDesc,int UniID,int FacID,int EduID,int NoOfTest,int NoOfAss,int NoOfPrac,int NoOfExam)
{
SQLiteDatabase db = this.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put(Col_2,ModCode);
contentValues.put(Col_3,ModDesc);
contentValues.put(Col_4,UniID);
contentValues.put(Col_5,FacID);
contentValues.put(Col_6,EduID);
contentValues.put(Col_7,NoOfTest);
contentValues.put(Col_8,NoOfAss);
contentValues.put(Col_9,NoOfPrac);
contentValues.put(Col_10,NoOfExam);
long result = db.insert(Table_Name, null, contentValues);
if(result==-1)
return false;
else
return true;
}
and the front end side of insert:
db = new DatabaseHelper(this);
textModCode = (EditText)findViewById(R.id.textModCode);
button_add = (Button)findViewById(R.id.button_add);
AddData();
The button press:
public void AddData(){
button_add.setOnClickListener(
new View.OnClickListener(){
#Override
public void onClick(View v){
boolean isInserted = db.insertData(textModCode.getText().toString(),"1",1,1,1,1,1,1,1);
if(isInserted=true)
Toast.makeText(MainActivity.this,"Data in",Toast.LENGTH_LONG).show();
else
Toast.makeText(MainActivity.this,"Sorry",Toast.LENGTH_LONG).show();
refresh();
}
}
);
}
Refresh:
public void refresh()
{
Cursor res = db.getAllData();
moduleList = new ArrayList<>();
if (res != null ) {
if (res.moveToFirst()) {
do {
Module m = new Module(res.getInt(res.getColumnIndex("ModID")),res.getInt(res.getColumnIndex("NoOfTest")),res.getInt(res.getColumnIndex("NoOfAss")),res.getInt(res.getColumnIndex("NoOfPrac")),res.getInt(res.getColumnIndex("NoOfExam")),res.getString(res.getColumnIndex("ModCode")),res.getString(res.getColumnIndex("ModDesc")),res.getString(res.getColumnIndex("UniID")),res.getString(res.getColumnIndex("FacID")),res.getString(res.getColumnIndex("EduID")));
moduleList.add(m);
}while (res.moveToNext());
}
}
/*
*/
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
moduleAdapter = new ModuleAdapter(this, moduleList);
recyclerView.setAdapter(moduleAdapter);
}
The recycler view displays everything right at first, but after scrolling the numbers begin to change with each scroll up or down.
When first open
1st scroll down and up
2nd scroll down and up
did I do anything wrong or what is going on? Thank you or any help
ModuleAdapter Class code
public class ModuleAdapter extends RecyclerView.Adapter<ModuleAdapter.ModuleViewHolder>{
private Context mCtx;
private List<Module> moduleList;
public ModuleAdapter(Context mCtx, List<Module> moduleList) {
this.mCtx = mCtx;
this.moduleList = moduleList;
}
#NonNull
#Override
public ModuleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.from(parent.getContext())
.inflate(R.layout.module_list, parent, false);
return new ModuleViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ModuleViewHolder holder, int position) {
Module module = moduleList.get(position);
holder.textModCodeView.setText(module.getModcode());
holder.textModuleDescView.setText(module.getModdesc());
holder.textEducatorView.setText(holder.textEducatorView.getText()+ module.getEducator());
holder.textNoOfTestView.setText(holder.textNoOfTestView.getText()+ String.valueOf(module.getNooftest()));
holder.textNoOfAssView.setText(holder.textNoOfAssView.getText()+ String.valueOf(module.getNoofass()));
holder.textNoOfPracView.setText(holder.textNoOfPracView.getText()+ String.valueOf(module.getNoofprac()));
holder.textNoOfExamView.setText(holder.textNoOfExamView.getText()+ String.valueOf(module.getNoofexam()));
Random r = new Random();
int red=r.nextInt(255 - 0 + 1)+0;
int green=r.nextInt(255 - 0 + 1)+0;
int blue=r.nextInt(255 - 0 + 1)+0;
GradientDrawable draw = new GradientDrawable();
draw.setShape(GradientDrawable.RECTANGLE);
draw.setColor(Color.rgb(red,green,blue));
holder.textModCodeView.setBackground(draw);
}
#Override
public int getItemCount() {
return moduleList.size();
}
class ModuleViewHolder extends RecyclerView.ViewHolder{
TextView textModCodeView,textModuleDescView,textEducatorView,textNoOfTestView,textNoOfAssView,textNoOfPracView,textNoOfExamView;
public ModuleViewHolder(View itemView) {
super(itemView);
textModCodeView = itemView.findViewById(R.id.textModCodeView);
textModuleDescView = itemView.findViewById(R.id.textModuleDescView);
textEducatorView = itemView.findViewById(R.id.textEducatorView);
textNoOfTestView = itemView.findViewById(R.id.textNoOfTestView);
textNoOfAssView = itemView.findViewById(R.id.textNoOfAssView);
textNoOfPracView = itemView.findViewById(R.id.textNoOfPracView);
textNoOfExamView = itemView.findViewById(R.id.textNoOfExamView);
}
}
}
Follow this steps
1.Clear you arraylist before adding all values moduleList.clear();
Refresh:
public void refresh()
{
moduleList.clear(); // add this line
Cursor res = db.getAllData();
moduleList = new ArrayList<>();
if (res != null ) {
if (res.moveToFirst()) {
do {
Module m = new Module(res.getInt(res.getColumnIndex("ModID")),res.getInt(res.getColumnIndex("NoOfTest")),res.getInt(res.getColumnIndex("NoOfAss")),res.getInt(res.getColumnIndex("NoOfPrac")),res.getInt(res.getColumnIndex("NoOfExam")),res.getString(res.getColumnIndex("ModCode")),res.getString(res.getColumnIndex("ModDesc")),res.getString(res.getColumnIndex("UniID")),res.getString(res.getColumnIndex("FacID")),res.getString(res.getColumnIndex("EduID")));
moduleList.add(m);
}while (res.moveToNext());
}
}
/*
*/
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
moduleAdapter = new ModuleAdapter(this, moduleList);
recyclerView.setAdapter(moduleAdapter);
}
2.change below code as i mention below (i think view get conflit)
holder.textEducatorView.setText("Educatore"+ module.getEducator());
holder.textNoOfTestView.setText("NoOfTestView"+ String.valueOf(module.getNooftest()));
holder.textNoOfAssView.setText("NoOfAssView"+ String.valueOf(module.getNoofass()));
holder.textNoOfPracView.setText("NoOfPracView"+ String.valueOf(module.getNoofprac()));
holder.textNoOfExamView.setText("textNoOfExamView"+ String.valueOf(module.getNoofexam()));
Related
I am displaying comments on a post using a recycler adapter. The code is set to scroll the recycler view to the bottom when the edit text is clicked, and when a new comment is posted by the current user.
If the keyboard is shown and the recycler view still does not touches the keyboard (there is like 2 to 4 comments displayed), the app crashes when the comment is posted. If there are many items (enough to go under the keyboard), the recyclerview scrolls and nothing crashes.
This is my code:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// some code
scrollToBottom = true; // this is initially false
loadComments();
}
});
private void loadComments () {
Query query = firebaseFirestore.collection...;
FirestoreRecyclerOptions<Model> options = new FirestoreRecyclerOptions.Builder<Model>()
.setLifecycleOwner(this)
.setQuery(query, Model.class)
.build();
adapter = new Adapter(options, this);
recyclerview.setHasFixedSize(true);
recyclerview.setLayoutManager(new LinearLayoutManager(this));
recyclerview.setAdapter(adapter);
if (scrollToBottom) {
scrollToBottom = false;
scrollToTheBottom();
}
}
private void scrollToTheBottom() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
recyclerview.smoothScrollToPosition(adapter.getItemCount());
}
}, 600);
}
Adapter code:
public class Adapter extends FirestoreRecyclerAdapter<Model, Adapter.ViewHolder> {
Context context;
TimeAgo timeAgo;
public Adapter(#NonNull FirestoreRecyclerOptions<Model> options, Context context) {
super(options);
this.context = context;
}
#Override
protected void onBindViewHolder(#NonNull final ViewHolder holder, int position, #NonNull Model model) {
final String userID = model.getUser_id();
String image = model.getImage();
String username = model.getUsername();
String comment = model.getComment();
Timestamp commentTimeAgo = model.getTimestamp();
String timestampString = String.valueOf(commentTimeAgo);
String[] noOpeningParentheses = timestampString.split("\\(");
String[] noClosingParentheses = noOpeningParentheses[1].split("\\)");
String[] noCommaAndSpace = noClosingParentheses[0].split(", ");
String[] secondsFromTimestamp = noCommaAndSpace[0].split("seconds=");
String[] nanosecondsFromTimestamp = noCommaAndSpace[1].split("nanoseconds=");
long millis = TimeUnit.SECONDS.toMillis(Long.parseLong(secondsFromTimestamp[1])) + TimeUnit.NANOSECONDS.toMillis(Long.parseLong(nanosecondsFromTimestamp[1]));
// Applying
if (image.equals("default")) {
holder.userImage.setImageResource(R.mipmap.no_image);
} else {
Glide.with(context).load(image).into(holder.userImage);
}
holder.userUsername.setText(username);
holder.comment.setText(String.valueOf(comment));
holder.commentTimeAgo.setText(timeAgo.getTimeAgo(context, millis));
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem, parent, false);
context = parent.getContext();
timeAgo = new TimeAgo();
return new ViewHolder(view);
}
public class ViewHolder extends RecyclerView.ViewHolder {
CircleImageView userImage;
TextView userUsername, comment, commentTimeAgo;
public ViewHolder(#NonNull View itemView) {
super(itemView);
userImage = itemView.findViewById(R.id.userimage);
userUsername = itemView.findViewById(R.id.userUsername);
comment = itemView.findViewById(R.id.comment);
commentTimeAgo = itemView.findViewById(R.id.timeago);
}
}
}
When viewing the logcat, I get an error on the 3rd line:
String timestampString = String.valueOf(timestamp);
String[] noOpeningParentheses = timestampString.split("\\(");
String[] noClosingParentheses = noOpeningParentheses[1].split("\\)"); // error here
String[] noCommaAndSpace = noClosingParentheses[0].split(", ");
String[] secondsFromTimestamp = noCommaAndSpace[0].split("seconds=");
String[] nanosecondsFromTimestamp = noCommaAndSpace[1].split("nanoseconds=");
long millis = TimeUnit.SECONDS.toMillis(Long.parseLong(secondsFromTimestamp[1])) + TimeUnit.NANOSECONDS.toMillis(Long.parseLong(nanosecondsFromTimestamp[1]));
This is a code that I wrote for converting a firebase firestore timestamp field to milliseconds.
What I'm getting in logcat is something like java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
I do not know how to solve this. Any help please?
Replace:
recyclerview.smoothScrollToPosition(adapter.getItemCount());
with:
int lastIndex = adapter.getItemCount()-1;
if(lastIndex!=-1)
{recyclerview.smoothScrollToPosition(lastIndex);}
I am new in android. I am using content provider for my app and want to delete an item from my sqlite database. it deletes the item from the database but the recyclerview does not show that it has been deleted except you go back and open the activity again before the deleted item disappears. I have looked through the code but I dont actually know what the problem is.
MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_selecte_problem_drawal);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitleTextColor(Color.parseColor("#FFFFFF"));
mRecyclerView = (RecyclerView) findViewById(R.id.selected_problem_recycle_view); // Instantiate Recyclerview
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setHasFixedSize(true);
selectedProblemsAdapter = new SelectedProblemsAdapter(this, null);
mRecyclerView.setAdapter(selectedProblemsAdapter);
getLoaderManager().initLoader(SELECTED_PROBLEMS_LOADER_ID, null,new CartLoader());
payForSelectedProblems = (Button)findViewById(R.id.payForSelectedProblems);
payForSelectedProblems.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (total > 0) {
Preferences.setDefaults("total", String.valueOf(total), getApplicationContext());
Intent intent = new Intent(SelectedProblems.this, SecondPayment.class);
startActivity(intent);
}else{
AlertDialog.Builder alert = new AlertDialog.Builder(SelectedProblems.this);
alert.setTitle("Alert");
alert.setMessage("Kindly Select a problem to continue...");
alert.setPositiveButton("OK",null);
alert.show();
}
}
});
}
public class CartLoader implements LoaderManager.LoaderCallbacks<Cursor> {
#Override
public Loader<Cursor> onCreateLoader(int i, Bundle bundle) {
return new CursorLoader(
SelectedProblems.this,
TranxavContract.CartEntries.CONTENT_URI,
SELECTED_PROBLEMS,
null,
null,
null
);
}
#Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
selectedProblemsAdapter.update(cursor);
total = getSelectedProblemTotal(cursor);
problemSelectedTotal.setText(CurrencyFormatter.currencyFormat(String.valueOf(total)));
}
#Override
public void onLoaderReset(Loader<Cursor> loader){
selectedProblemsAdapter.update(null);
}
public double getSelectedProblemTotal(Cursor cursor){
while (cursor.moveToNext()){
total = total + Double.parseDouble(cursor.getString(SelectedProblems.PRICE));
}
return total;
}
}
Adapter
public SelectedProblemsAdapter(Context context, Cursor cursor) {
this.context = context;
this.cursor = cursor;
}
#NonNull
#Override
public SelectedProblemsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.activity_selected_problems_content, null, false);
return new SelectedProblemsViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull SelectedProblemsViewHolder holder, final int position) {
if (this.cursor != null){
this.cursor.moveToPosition(position);
priceIndex = cursor.getColumnIndex(TranxavContract.CartEntries.PRICE);
problemsIndex = cursor.getColumnIndex(TranxavContract.CartEntries.PROBLEMS);
id = cursor.getString(idIndex);
problems = cursor.getString(problemsIndex);
price = cursor.getString(priceIndex);
formatted_price = CurrencyFormatter.currencyFormat(price);
holder.selectedProblemPrice.setText(formatted_price);
holder.selectedProblems.setText(problems);
holder.remove_problem_from_cart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
context.getContentResolver().delete(
TranxavContract.CartEntries.CONTENT_URI,
TranxavContract.CartEntries.PROBLEMS + " = ?",
new String[] { problems }
);
Toast.makeText(context, problems + " Item Removed from Problem Selected" + "with postion " + position, Toast.LENGTH_SHORT).show();
notifyItemRemoved(position);
notifyDataSetChanged();
}
});
}
}
#Override
public int getItemCount() {
return (null != cursor ? cursor.getCount(): 0);
}
public void update(Cursor cursor) {
this.cursor = cursor;
notifyDataSetChanged();
}
class SelectedProblemsViewHolder extends RecyclerView.ViewHolder{
TextView selectedProblems, selectedProblemPrice, selectedProblemTotal;
Button remove_problem_from_cart;
public SelectedProblemsViewHolder(View itemView) {
super(itemView);
selectedProblems = itemView.findViewById(R.id.selected_problems);
selectedProblemPrice = itemView.findViewById(R.id.selected_problem_price);
selectedProblemTotal = itemView.findViewById(R.id.selectedProblemTotal);
remove_problem_from_cart = itemView.findViewById(R.id.remove_problem_from_cart);
}
}
Anybody who can help me.
For every delete, update your adapter like this
selectedProblemsAdapter.notifydatasetchanged();
Assuming all your deleting process is correct and you want to show animation all over your list in RecyclerView.
Instead of using
notifyItemRemoved(position)
you could implement
notifyItemRangeChanged(position, getItemCount());
notifyItemRangeChanged() notifies the RecyclerView Adapter that positions of element in adapter has been changed from position.
Here is a reference for you.
Hope it helps!
May be the problem is the list hasn't been reload after you deleted the record in db. You can try the method getLoaderManager().restartLoader(int id, Bundle args, LoaderCallbacks<D> callback) this should be restart the query and update it from the db. I hope so. Check more at here
After Deleting recall your display method
(If selectedProblemsAdapter.notifydatasetchanged(); this method is not work)
I building a music player that has a tab layout. One of the tabs is "Genres"(Genre.java) that displays the genres of songs in RecyclerView( songs that are present on the external storage of the android phone, by querying it). I have set onClickListeners too for the genres in the RecyclerView. So, when I click one the genres it should take me to another activity (GenresSongs.java) that displays all the song belonging to that clicked genre.
My problem:
When I click any of the genres, it takes me to another activity but it displays the song that was last added to the array. No matter which genre I click it takes me to the same song.
What I want:
When I click one of genres in the list it should take me to the song that belongs to the clicked genre. I hope you are getting my point. I'm passing GenreID as intent.
Genre.java(class that displays the genre of all the songs) :
public class Genres extends Fragment {
private static final String TAG = "Genres";
RecyclerView recyclerView_genre;
GenresAdapter genresAdapter;
ArrayList<GenresModel> Genrelist = new ArrayList<>();
Cursor genrecursor;
long id;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.genres_activity, container, false);
recyclerView_genre = view.findViewById(R.id.recyclerView_genre);
LinearLayoutManager genreLayout = new LinearLayoutManager(getContext());
recyclerView_genre.setLayoutManager(genreLayout);
final Uri uri = MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI;
genrecursor = getActivity().getContentResolver().query(uri,null,null, null, null);
if (genrecursor != null) {
if (genrecursor.moveToFirst()) {
do {
id = genrecursor.getLong(genrecursor.getColumnIndex(MediaStore.Audio.Genres._ID));
String name = genrecursor.getString(genrecursor.getColumnIndex(MediaStore.Audio.Genres.NAME));
GenresModel genresModel = new GenresModel(id,name);
Genrelist.add(genresModel);
Collections.sort(Genrelist, new Comparator<GenresModel>() {
#Override
public int compare(GenresModel lhs, GenresModel rhs) {
return lhs.getGenreName().compareTo(rhs.getGenreName());
}
});
} while (genrecursor.moveToNext());
}
genrecursor.close();
}
genresAdapter = new GenresAdapter(getContext(), Genrelist, new GenresAdapter.GenreItemClickListener() {
#Override
public void onClickListener(GenresModel genresModel, int GenrePosition) {
Intent nIntent = new Intent(getContext(), GenresSong.class);
nIntent.putExtra("genre_ID", id);
startActivity(nIntent);
}
});
recyclerView_genre.setAdapter(genresAdapter);
genresAdapter.notifyDataSetChanged();
return view;
}
GenresAdapter.java(the adapter class of Genres.java):
public class GenresAdapter extends RecyclerView.Adapter<GenresAdapter.GenresHolder> {
private Context gContext;
private ArrayList<GenresModel> GenreList = new ArrayList<>();
private GenreItemClickListener listenerGenre;
public GenresAdapter(Context gContext, ArrayList<GenresModel> genreList, GenresAdapter.GenreItemClickListener listenerGenre) {
this.gContext = gContext;
GenreList = genreList;
this.listenerGenre = listenerGenre;
}
#Override
public GenresAdapter.GenresHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view3 = LayoutInflater.from(gContext).inflate(R.layout.row_genre, parent, false);
return new GenresHolder(view3);
}
#Override
public void onBindViewHolder(GenresAdapter.GenresHolder holder, int position) {
final GenresModel genresModel1 = GenreList.get(position);
holder.genreText.setText( genresModel1.getGenreName());
holder.bindSong(genresModel1, listenerGenre);
}
#Override
public int getItemCount() {
return GenreList.size();
}
public class GenresHolder extends RecyclerView.ViewHolder {
TextView genreText;
public GenresHolder(View itemView) {
super(itemView);
genreText = itemView.findViewById(R.id.genreText);
}
public void bindSong(final GenresModel genresModel1, final GenreItemClickListener listenerGenre) {
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listenerGenre.onClickListener(genresModel1, getLayoutPosition());
}
});
}
}
public interface GenreItemClickListener{
void onClickListener(GenresModel genresModel, int GenrePosition);
}
GenresSong.java(class that is supposed to display songs when genre is clicked):
public class GenresSong extends Activity {
RecyclerView recyclerView_genreSong;
ArrayList <GenreSongModel> GenreSongList = new ArrayList<>();
GenresSongAdapter genresSongAdapter;
long genreID;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.genres_details);
recyclerView_genreSong = findViewById(R.id.recyclerView_genreSong);
LinearLayoutManager l1 = new LinearLayoutManager(getApplicationContext());
recyclerView_genreSong.setLayoutManager(l1);
genreID = getIntent().getExtras().getLong("genre_ID");
Uri uri = MediaStore.Audio.Genres.Members.getContentUri("external", genreID);
String[] projection ={MediaStore.Audio.Media.TITLE};
Cursor cursor = getApplicationContext().getContentResolver().query(uri, projection, null, null, null);
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
String name = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));
GenreSongModel s = new GenreSongModel(name);
GenreSongList.add(s);
} while (cursor.moveToNext());
}
cursor.close();
Collections.sort(GenreSongList, new Comparator<GenreSongModel>() {
#Override
public int compare(GenreSongModel lhs, GenreSongModel rhs) {
return lhs.getSongName().compareTo(rhs.getSongName());
}
});
}
genresSongAdapter = new GenresSongAdapter(getApplicationContext(), GenreSongList);
recyclerView_genreSong.setAdapter(genresSongAdapter);
genresSongAdapter.notifyDataSetChanged();
}
GenresSongAdapter.java(adapter class for GenresSong.java):
public class GenresSongAdapter extends RecyclerView.Adapter<GenresSongAdapter.GenresSongHolder> {
Context gsContext;
ArrayList<GenreSongModel> GenresSongList2 = new ArrayList<>();
public GenresSongAdapter(Context gsContext, ArrayList<GenreSongModel> genresSongList2) {
this.gsContext = gsContext;
GenresSongList2 = genresSongList2;
}
#Override
public GenresSongAdapter.GenresSongHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v5 = LayoutInflater.from(gsContext).inflate(R.layout.row_genredetails, parent, false);
return new GenresSongHolder(v5);
}
#Override
public void onBindViewHolder(GenresSongAdapter.GenresSongHolder holder, int position) {
GenreSongModel genreSongModel = GenresSongList2.get(position);
holder.genreSongName.setText(genreSongModel.getSongName());
}
#Override
public int getItemCount() {
return GenresSongList2.size();
}
public class GenresSongHolder extends RecyclerView.ViewHolder {
TextView genreSongName;
public GenresSongHolder(View itemView) {
super(itemView);
genreSongName = itemView.findViewById(R.id.genreSongName);
}
}
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'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.