I have a recyclerview in a dialog fragment, which hosts a tab layout, containing a list of checkable items and a button each. When an item is selected, it is passed on click through the bundle to this parent dialog fragment like this:
doneBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
retrieveSessions();
}
});
private void retrieveSessions() {
NewProgramDialog dialog = new NewProgramDialog(); // parent dialog fragment is passed the list items here
Bundle bundle = new Bundle();
String s = new Gson().toJson(myItemsList);
bundle.putString(KEY_MY_SESSIONS, s);
bundle.putBoolean("from_selections", true);
dialog.setArguments(bundle);
dialog.show(getChildFragmentManager(), "NewProgramDialog");
dismiss();
}
The data for recyclerview is received through a bundle lie shown above and the list items are retrieved using Gson and converted to type String, a query is run on the database to get the session model class info.
These sessions are added to the adapter arraylist like below:
private void populateSessions() {
addProgramSessionsRV.setHasFixedSize(true);
addProgramSessionsRV.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.HORIZONTAL, false));
// TODO: 2/05/2019 show the added sessions here
Bundle bundle = getArguments();
if (bundle != null) {
String s = bundle.getString(KEY_MY_SESSIONS); / getting the items from bundle
myItemsList = new Gson().fromJson(s, ArrayList.class); // parsing to List<String> type
Log.d(TAG, "Items size:\t" + myItemsList.size()); //works
}
adapter = new AddProgramSessionsAdapter(getActivity(), sessionsList);
addProgramSessionsRV.setAdapter(adapter);
Log.d(TAG, "Items in adapter:\t" + adapter.getItemCount()); // shows total items received from bundle
for (String s : myItemsList){
Log.d(TAG, "Ids:\t" + s);
Sessions session = SQLite.select()
.from(Sessions.class)
.where(Sessions_Table.prog_sessionId.eq(s))
.querySingle();
sessionsList.add(session);
Log.d(TAG, "Session List Size:\t" + sessionsList.size());
adapter = new AddProgramSessionsAdapter(getActivity(), sessionsList);
addProgramSessionsRV.setAdapter(adapter);
Log.d(TAG, "Items in adapter:\t" + adapter.getItemCount());
}
}
Still the ui shows no items from this method. I have added the data manually using this snippet and it shows Session 1 item in view but not the data from db in for loop.
Test Case:
Sessions sessions = new Sessions();
sessions.setSession_name("Test one");
sessions.setProgram_id("234");
sessions.setProg_sessionId("91");
sessionsList.add(sessions);
adapter = new AddProgramSessionsAdapter(getActivity(), sessionsList);
addProgramSessionsRV.setAdapter(adapter);
Log.d(TAG, "Items in adapter:\t" + adapter.getItemCount());
Is there any reason why setting the adapter to a list which has items does not work in the for loop db query (works)? Please explain to me why the ui shows nothing. Thanks.
Here's the adapter code:
public class AddProgramSessionsAdapter extends RecyclerView.Adapter<AddProgramSessionViewHolder> {
private final Context context;
private List<Sessions> itemsList;
public AddProgramSessionsAdapter(Context context, List<Sessions> itemsList) {
this.context = context;
this.itemsList = itemsList;
}
#Override
public AddProgramSessionViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.add_program_sessions_items_layout, parent, false);
return new AddProgramSessionViewHolder(view);
}
#Override
public void onBindViewHolder(AddProgramSessionViewHolder viewholder, int position) {
Sessions sessions = itemsList.get(position);
viewholder.add_program_sessionNameTV.setText(sessions.session_name);
Picasso.with(context)
.load(R.drawable.app_logo_resized)
.into(viewholder.add_program_sessionIV);
}
#Override
public int getItemCount() {
if (itemsList == null) {
return 0;
}
return itemsList.size();
}
}
Related
I have an app which is storing data in Room Database. This is an movie app and when user add new movie to his list, it doesn't work in synchronization. When I close app and open again, list will being updated. Users adding film button is in one fragment, list is in another fragment. They are not in same fragment. It add database without problem but I need to make synchronization between these two fragments.
This is List Fragment.
public class ListFragment extends Fragment {
ImageView listTitleImage;
RecyclerView recyclerView;
List<MainData> dataList = new ArrayList<>();
LinearLayoutManager linearLayoutManager;
RoomDB database;
RecyclerViewFavoritesAdapter adapter;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_list,container,false);
listTitleImage = v.findViewById(R.id.listTitleImage);
recyclerView = v.findViewById(R.id.recyclerViewFavorites);
database = RoomDB.getInstance(v.getContext());
dataList = database.mainDao().getAll();
linearLayoutManager = new LinearLayoutManager(v.getContext());
recyclerView.setLayoutManager(linearLayoutManager);
adapter = new RecyclerViewFavoritesAdapter(v.getContext(),dataList);
recyclerView.setAdapter(adapter);
return v;
}
}
This is menu click method which includes adding in list.
#Override
public boolean onMenuItemClick(MenuItem item) {
if(item.getItemId() == R.id.menuAdd){
int movie_id = resultList.get(pos).getMovieId();
String title = resultList.get(pos).getTitle();
String posterpath = resultList.get(pos).getPoster_path();
database = RoomDB.getInstance(context);
MainData mainData = new MainData();
mainData.setMovie_id(movie_id);
mainData.setMovie_name(title);
mainData.setMovie_poster(posterpath);
int movie_id_in_database = database.mainDao().get_movie_id(movie_id);
if(movie_id_in_database == 0){
database.mainDao().insert(mainData);
} else{
Toast.makeText(context, "You already have that movie in list !", Toast.LENGTH_SHORT).show();
}
return true;
}
else if(item.getItemId() == R.id.menuShowDetails){
int movieId = resultList.get(pos).getMovieId();
// Intent intent1 = new Intent(context, MovieDetails.class);
// intent1.putExtra("movie_id",movieId);
// context.startActivity(intent1);
return true;
}
return false;
}
In the parent activity, I have an edit text in a toolbar, and user can make a search through the data displayed by the recyclerview.
When the user push enter key down, the string in the edittext is sent to the fragment by :
Bundle bundle = new Bundle();
bundle.putString(predResult, placeid);
MapFragment mapFragment = new MapFragment();
ListRestFragment listRestFragment = new ListRestFragment();
mapFragment.setArguments(bundle);
listRestFragment.setArguments(bundle);
getSupportFragmentManager().beginTransaction()
.replace(R.id.map, mapFragment)
.replace(R.id.list_frag, listRestFragment)
.commit();
but, unfortunatly, the recyclerview is not resfreshed while my adapter is notified the data is changed as it shown below:
private void queryToList(Query query) {
query.addSnapshotListener((queryDocumentSnapshots, e) -> {
restaurantList = queryDocumentSnapshots.toObjects(Restaurant.class);
if (!myPrediction.contains("myPrediction")) {
System.out.println(myPrediction);
for (Restaurant item : restaurantList) {
if (item.getRestaurantID().contains(myPrediction)) {
restaurantListPred = new ArrayList<>();
restaurantListPred.add(item);
updateUI(restaurantListPred);
}
}
} else updateUI(restaurantList);
});
}
private void updateUI(List<Restaurant> restaurants) {
configureFab();
configureRecyclerView(restaurants);
}
private void configureRecyclerView(List<Restaurant> restaurant) {
this.adapter = new RestaurantAdapterClassic(restaurant);
this.recyclerView.setAdapter(this.adapter);
this.recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(recyclerView.getContext(), DividerItemDecoration.VERTICAL);
recyclerView.addItemDecoration(new SimpleItemDecorator(getContext()));
}
the new List is updated automatically when the user makes his request, but the recyclerView doesn't display the new data.
if you want to check my adapter implementation:
public class RestaurantAdapterClassic extends RecyclerView.Adapter<RestaurantViewHolder> {
private List<Restaurant> restaurantsList;
// CONSTRUCTOR
public RestaurantAdapterClassic(List<Restaurant> restaurants) {
this.restaurantsList = restaurants;
}
#Override
public RestaurantViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// CREATE VIEW HOLDER AND INFLATING ITS XML LAYOUT
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.listview_pattern, parent, false);
return new RestaurantViewHolder(view);
}
#Override
public void onBindViewHolder(RestaurantViewHolder viewHolder, int position) {
viewHolder.updateWithRestaurant(this.restaurantsList.get(position));
}
// RETURN THE TOTAL COUNT OF ITEMS IN THE LIST
#Override
public int getItemCount() {
return this.restaurantsList.size();
}
public Restaurant getRestaurant(int position) {
return this.restaurantsList.get(position);
}
public void filterList(List<Restaurant> filteredList) {
restaurantsList = filteredList;
notifyDataSetChanged();
}
}
where is my error or my misunderstanding?
EDIT SOLUTION -
Create an Interface
Actually, to send the new data data from my Parent Activity to my Fragment with a listener to observe when the data changes.
Keep The data reference sent to the adapter
Actually, the main big problem that I had was my adapter doesn't refresh when I sent new array. The reason was an adapter creates a reference with the list/array. if you want to refresh it, you need to keep this reference by get the list, erase it, and put/add new data inside by the method addALL for example.
First of all, adapter.notifyDataSetChanged(); doesn't have any effect in the code as inside updateUI you create the adapter every time you call it.
I think, the main problem is in here:
if (item.getRestaurantID().contains(myPrediction)) {
restaurantListPred = new ArrayList<>();
restaurantListPred.add(item);
updateUI(restaurantListPred);
}
This block doesn’t execute at all. Thats why the list not updated.
I'm retrieving data using a FirestoreRecyclerAdapter, and, on completion, I need to check whether any items have been retrieved or not. I can't figure out how to do this.
I'm calling it from a class called FragmentChartsList, shown below. This should set up the adapter initially, with "name" as the value for mOrder. Later, the Activity which contains this Fragment can call setOrderField() with a different value of mOrder, which the user has selected from a Spinner.
Each time setOrderField() is called, a new adapter instance is created and attached to the recyclerView. At this point I need to check whether the new version of the adapter contains any data, and either show a "no Charts found" message, or show the Charts which were retrieved (obviously if the list is just being sorted, then the number of items remains the same, but I'm going to be expanding this to allow the user to filter the Charts by different criteria, so the number of Charts returned will change).
Currently, setOrderField() calls refreshViewOnNewData(), which should find out how many Charts are being shown; if it's 0, it should show the "no Charts found" message, and if it's >0 it should show the RecyclerView containing the Charts.
At the moment, I'm always getting a value of 0 when I try to count the Charts. I suspect it's because the adapter hasn't finished retrieving them from the database yet, but I can't find anything that allows me to add some kind of "onComplete" listener so that I know it's finished.
Can anyone suggest how I can achieve this?
public abstract class FragmentChartsList extends Fragment {
private FirebaseFirestore mDatabaseRef;
private ChartListAdapter mAdapter;
private Query mChartsQuery;
private RecyclerView mRecycler;
private String mOrder = "name";
private TextView mLoadingList, mEmptyList;
public FragmentChartsList() {}
#Override
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(
R.layout.fragment_charts_list, container, false);
mRecycler = rootView.findViewById(R.id.charts_list);
mRecycler.setHasFixedSize(true);
mLoadingList = rootView.findViewById(R.id.loading_list);
mEmptyList = rootView.findViewById(R.id.empty_list);
// Set up Layout Manager, and set Recycler View to use it
LinearLayoutManager mManager = new LinearLayoutManager(getActivity());
mManager.setReverseLayout(true);
mManager.setStackFromEnd(true);
mRecycler.setLayoutManager(mManager);
// Connect to the database
mDatabaseRef = FirebaseFirestore.getInstance();
setOrderField(mOrder); // Initialised to "name"
return rootView;
}
#Override
public void onStart() {
super.onStart();
mAdapter.startListening();
}
#Override
public void onStop() {
super.onStop();
mAdapter.stopListening();
}
#Override
public void onDestroy() {
super.onDestroy();
mAdapter.stopListening();
}
// HELPER FUNCTIONS
public void setOrderField(String order) {
mOrder = order;
mChartsQuery = getQuery(mDatabaseRef, mOrder);
// Update recycler options
FirestoreRecyclerOptions<Chart> recyclerOptions = new FirestoreRecyclerOptions.Builder<Chart>()
.setQuery(mChartsQuery, Chart.class)
.build();
mAdapter = new ChartListAdapter(recyclerOptions, getActivity());
mAdapter.startListening();
mRecycler.swapAdapter(mAdapter, true);
refreshViewOnNewData();
}
private void refreshViewOnNewData() {
// Hide "loading" text
mLoadingList.setVisibility(View.GONE);
// Check number of charts being shown
//if (mAdapter != null && (mAdapter.getCount() > 0)) {
// If > 0, show Charts
mEmptyList.setVisibility(View.GONE);
mRecycler.setVisibility(View.VISIBLE);
} else {
// If number of Charts = 0
// show "no charts"
mEmptyList.setVisibility(View.VISIBLE);
mRecycler.setVisibility(View.GONE);
}
}
}
The adapter class looks like this:
public class ChartListAdapter extends FirestoreRecyclerAdapter<Chart, ChartViewHolder> {
private Activity mActivity;
private int mCount;
public ChartListAdapter(FirestoreRecyclerOptions<Chart> recyclerOptions, Activity activity) {
super(recyclerOptions);
mActivity = activity;
}
#Override
protected void onBindViewHolder(#NonNull ChartViewHolder holder, int position, #NonNull Chart model) {
final String chartKey = this.getSnapshots().getSnapshot(position).getId();
model.setKey(chartKey);
// Set click listener for the chart
// On click, the user can view the chart
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mActivity, ActivityViewChart.class);
intent.putExtra("ChartKey", chartKey);
mActivity.startActivity(intent);
}
});
// Implement long-click menu
mActivity.registerForContextMenu(holder.itemView);
// Bind Chart to ViewHolder
holder.bindToChart(model);
}
#NonNull
#Override
public ChartViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_chart, parent, false);
return new ChartViewHolder(view);
}
#Override
public void onDataChanged() {
super.onDataChanged();
mCount = getItemCount();
}
public int getCount() {
return mCount;
}
}
Figured this out... I needed to set a listener on the query instead.
So, instead of having the call to refreshViewOnNewData from setOrder above, I now have:
mChartsQuery.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot queryDocumentSnapshots, #Nullable FirebaseFirestoreException e) {
if (queryDocumentSnapshots != null) {
mLoadingList.setVisibility(View.GONE);
if(queryDocumentSnapshots.size() > 0) {
mEmptyList.setVisibility(View.GONE);
mRecycler.setVisibility(View.VISIBLE);
}else {
mEmptyList.setVisibility(View.VISIBLE);
mRecycler.setVisibility(View.GONE);
}
}
}
});
}
Also removed mCount from the adapter class, along with getCount and onDataChanged
Sincere apologies for no code, I'm leaving for a wedding and it was either post code or explain my situation.
I've searched Stack and see many posts for Recycler Adapter to Fragment (that created the adapter) interfaces.
A minor few for Fragment(created the adapter) to Adapter posts but they are not nearly as clear.
My situation is this:
On Main Activity, when App is running:
1) Fragment Lyrics (created the REcycler ADapter that is set into a Lyric Recycler View)
2) Fragment Microphone ( speech recognition microphone functionality and XML icon).
What I want to happen is:
user activates Microphone and speaks, that resulting data is passed to the ADAPTER java file and activates a method on the ADAPTER, causing a visual change to RecyclerView Viewholder on the screen.
Yes, I know this is probably bad architecture. It's for a school project, I'm learning, and I've run out of time.
* What I can do so far *
I have activated the pre-made OnClick listerner for the Adapter (when a user clicks on a View) and OnScroll for the RecyclerView (user scrolls, it fires a method in the Adapter that causes the current View to change).
I have made interface for Passing Speech data from Microphone Fragment, through the Main Activity, to the Lyrics Fragment.
On Main, I simply create an instance of the Lyrics Fragment, then call a custom method on Lyrics Fragment that takes the speech data. Something like this.
LyricsFragment.TakeSpeechData(speech data);
* What my plans was...*
When the speech data arrives on Lyrics Fragment, I thought I could just write something like:
MyRecyclerAdapter.SomeMethodOnAdapter (speech data);
I would be home free at this point.
It doesn't work
No go. I get a null pointer exception here. The MyRecyclerAdapter part of the method call is null. I've looked that up and not sure how to fix it.
I'm assuming I'm referencing the original Adapter that was created when the Fragment layed down the RecyclerView and set everything. It's the same global variable for the Adapter on Fragment Lyrics and I'm assuming it "lives on".
I'm sure I'm missing on fundamental Java principles but i don't know what.
I've spent hours and hours on this trying , reading, researching. I'm totally stuck. Please help.
EDIT: Here is my code for VerseFragment (I'm referring to it as "Lyrics" Fragment in my post). Note this Fragment is loaded, created, and functional with recyclerView on screen. Before the user uses the micrphone fragment, which is also on screen, this has already been created.
public class VersesList extends Fragment {
#BindView(R.id.versesRecycleView) RecyclerView versesRecycleView;
#BindView(R.id.songNameTextView) TextView songName;
#BindView(R.id.artistTextView)TextView artistName;
private SharedPreferences mSharedPreferences;
LinearLayoutManager llm;
List verseList;
List finalModVerseList;
public VerseAdapter verseAdapter;
// temporary
private SharedPreferences.Editor editor;
public VersesList() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_verses_list, container, false);
ButterKnife.bind(this, view);
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
editor=mSharedPreferences.edit();
displayArtistAndSongName();
lyricsToVerseList();
setVersesIntoRecyclerView();
setVersesScrollListener();
//temp
storeAllVerseLevels();
return view;
}
public static VersesList newInstance(String lyrics){
VersesList versesListFragment = new VersesList();
Bundle args = new Bundle();
args.putString("lyrics", lyrics);
versesListFragment.setArguments(args);
return versesListFragment;
}
public void lyricsToVerseList(){
String lyrics = getArguments().getString("lyrics", "");
verseList = new ArrayList<String>();
finalModVerseList = new ArrayList<String>();
verseList= Arrays.asList(lyrics.split("\n"));
int endOfFinalList=verseList.indexOf("...");
for (int i = 0; i < endOfFinalList; i++) {
if(!verseList.get(i).toString().equals("")){
String addThisVerse = verseList.get(i).toString();
//check on length of verse, if too short add next, check again
int numberOfWords = addThisVerse.split(" ").length;
while (numberOfWords < 10 && i < endOfFinalList) {
i++;
addThisVerse += " " + verseList.get(i).toString();
numberOfWords = addThisVerse.split(" ").length;
}
finalModVerseList.add(addThisVerse);
}
}
}
public void displayArtistAndSongName(){
String song = '"'+mSharedPreferences.getString(SONG_NAME, null)+'"';
String artist = "by "+mSharedPreferences.getString(ARTIST_NAME, null);
songName.setText(song);
artistName.setText(artist);
}
public void setVersesIntoRecyclerView(){
verseAdapter = new VerseAdapter(finalModVerseList, (MainActivity)getActivity(), versesRecycleView);
versesRecycleView.setAdapter(verseAdapter);
llm = new LinearLayoutManager(getActivity(),LinearLayoutManager.HORIZONTAL, false);
versesRecycleView.setLayoutManager(llm);
PagerSnapHelper helper = new PagerSnapHelper();
helper.attachToRecyclerView(versesRecycleView);
}
private void storeLevel(int indexNumber) {
editor.putInt(String.valueOf(indexNumber), 1).apply();
}
private void storeAllVerseLevels(){
for (int i=0; i< finalModVerseList.size();i++){
storeLevel(i);
}
for (int j=0; j< finalModVerseList.size();j++){
String level = String.valueOf(mSharedPreferences.getInt(String.valueOf(j), -1));
Log.d("In Shared Preferences ", "Verse "+j+" Level "+level);
}
}
public void checkSpeech(String text){
List<String> temp = new ArrayList<>();
temp.add("test");
VerseAdapter adapter = new VerseAdapter(temp, (MainActivity)getActivity(), versesRecycleView);
try {
adapter.resetVerse();
}catch (NullPointerException e){
Log.d("Null", e.toString());
}
}
public void setVersesScrollListener(){
versesRecycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == 0) {
verseAdapter.resetVerse();
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
}
});
}
}
When you are calling the method from your adapter, is MyRecyclerAdapter an instance or the class? To call someMethodOnAdpater(speechData), you must use an instance . Xia is using an instance.
If you need to call an adapter method from within the fragment in which it was created, you can store it in a variable like this.
MyRecyclerAdapter adapter;
#Override
public View onCreateView(...) {
...
adapter = new MyRecyclerAdapter();
myRecyclerView.setAdapter(adapter);
...
}
public void takeSpeechData(String data) {
adapter.someMethodAdapter(data);
}
Edit:
I'm not sure why the same adapter used by your recyclerview is null after being set. Calling an adapter from is definitely possible (I tested a basic example). The code in my example doesn't differ from what you said you had previously, though. I have upvoted your question for visibility.
**Edit: Add Mic Fragment, it has the interface **
package com.blueoxgym.javainthedark.Fragments;
/**
* A simple {#link Fragment} subclass.
*/
public class MicFragment extends Fragment implements View.OnClickListener {
#BindView(R.id.progressBarMic)
ProgressBar micLevels;
#BindView(R.id.btn_mic)
ImageButton btnMicrophone;
private SpeechRecognizer speech = null;
private Intent recognizerIntent;
public final static String TAG = "In speech mode";
public FragmentManager fragmentManager;
private SharedPreferences mSharedPreferences;
private SharedPreferences.Editor mEditor;
private String trackName;
private String artistName;
private CallMainLoadVerseFragment loadVerseFragment;
private CheckSpeech checkSpeechOnVerse;
public MicFragment() {
// Required empty public constructor
}
public static MicFragment newInstance (){
MicFragment micFragment = new MicFragment();
return micFragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_mic, container, false);
ButterKnife.bind(this, view);
this.loadVerseFragment = (CallMainLoadVerseFragment) getActivity();
this.checkSpeechOnVerse = (CheckSpeech) getActivity();
btnMicrophone.setOnClickListener(this);
fragmentManager = getFragmentManager();
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
mEditor = mSharedPreferences.edit();
return view;
}
#Override
public void onClick(View v) {
if (v == btnMicrophone) {
startSpeechToText();
}
}
class listener implements RecognitionListener {
...
#Override
public void onResults(Bundle results) {
String str = new String();
Log.d(TAG, "onResults " + results);
ArrayList<String> data = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
String text = data.get(0).toLowerCase().replace("by","");
Fragment currentFragment = fragmentManager.findFragmentById(R.id.content_frame);
if (currentFragment.toString().contains("LyricSearch")){
searchForSong(text);
} else if (currentFragment.toString().contains("VersesList")){
-----------> Here it is called checkSpeechOnVerse.checkingSpeech(text);
}
}
}
public void startSpeechToText(){
btnMicrophone.setBackgroundResource(R.drawable.circle_green);
speech=SpeechRecognizer.createSpeechRecognizer(getContext());
speech.setRecognitionListener(new listener());
recognizerIntent= new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_PREFERENCE, "en-US");
recognizerIntent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getActivity().getPackageName());
recognizerIntent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
recognizerIntent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 5);
speech.startListening(recognizerIntent);
}
...
...
public interface CheckSpeech {
void checkingSpeech (String text);
}
}
MainActivity, implements CheckSpeech Interface
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, MicFragment.CallMainLoadVerseFragment, MicFragment.CheckSpeech {
....
...
#Override
public void checkingSpeech(String text) {
VersesList versesList = new VersesList();
--------> Now, I'm pass data from Main to VersesList Fragment(it has the original Adapter)
versesList.checkSpeech(text);
}
VersesList Fragment, where I try to call Adapter
public class VersesList extends Fragment {
....
private VerseAdapter verseAdapter;
setVersesIntoRecyclerView();
....
<---ADAPTER IS MADE AND SET HERE----.
public void setVersesIntoRecyclerView(){
verseAdapter = new VerseAdapter(finalModVerseList, (MainActivity)getActivity(), versesRecycleView);
versesRecycleView.setAdapter(verseAdapter);
llm = new LinearLayoutManager(getActivity(),LinearLayoutManager.HORIZONTAL, false);
versesRecycleView.setLayoutManager(llm);
PagerSnapHelper helper = new PagerSnapHelper();
helper.attachToRecyclerView(versesRecycleView);
}
public void checkSpeech(String text){
-------> NPE NPE
versesAdapter.someMethodOnAdapter(text);
}
public void setVersesScrollListener(){
versesRecycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == 0) {
BUT THIS WORKS!!! No NPE. --------> verseAdapter.resetVerse();
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// VerseAdapter.VerseViewHolder view = versesRecycleView.findViewHolderForAdapterPosition(llm.findFirstVisibleItemPosition());
}
});
}
If you need to call an adapter method from within the fragment in which it was created, you can store it in a variable within that fragment.
MyRecyclerAdapter adapter;
#Override
public View onCreateView(...) {
...
adapter = new MyRecyclerAdapter();
myRecyclerView.setAdapter(adapter);
...
}
public void takeSpeechData(String data) {
adapter.someMethodAdapter(data);
}
Then you can call that method directly from another fragment. (link to accessing fragments)
VersesList versesList = (VersesList) getActivity().getSupportFragmentManager.findFragmentById(containerId);
versesList.takeSpeechData("data");
gif of example
I developing news feed like twitter, facebook and etc.
I have a server that gives me portions of articles for 10 pieces.
When I scroll down, new articles are loaded, added to the database and displayed in RealmRecyclerView.
I added SwipeRefreshLayout to update the data (in the case when new quotes came in).
I have a problem with adding new items to the top when i use SwipeRefreshLayout.
My idea was to sort new articles on id. In that case, when I scroll down the items with the smaller ones the id will be at the bottom, and when I use SwipeRefreshLayout new articles with higher id are download and adding in top list.
MyFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_view_all_quotes, container, false);
swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setOnRefreshListener(this);
Realm.init(getActivity());
realm = Realm.getDefaultInstance();
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
adapter = new QuoteAdapter(realm.where(QuoteObject.class).findAllSortedAsync("id", Sort.DESCENDING), getActivity());
recyclerView.setAdapter(adapter);
return view;
}
#Override
public void onRefresh() {
int position = realm.where(QuoteObject.class).findAll().size();
DownloadDataFromServer.DownloadQuotes downloadQuotes =
new DownloadDataFromServer.DownloadQuotes();
try {
DownloadDataFromServer.DownloadQuotes.FlagQuotes = true;
downloadQuotes.execute(position+1).get();
}catch (Exception e){
Log.e(TAG, "Error", e);
}finally {
swipeRefreshLayout.setRefreshing(false);
}
}
RealmRecyclerViewAdapter
class QuoteAdapter extends RealmRecyclerViewAdapter<QuoteObject, QuoteAdapter.AllQuotesViewHolder> {
QuoteAdapter(OrderedRealmCollection<QuoteObject> quotes, Context context) {
super(quotes, true);
this.context = context;
if (quotes.size() == 0) downloadData(0);
}
.
.
.
#Override
public void onBindViewHolder(final QuoteAdapter.AllQuotesViewHolder viewHolder, int position) {
if (position == getData().size() - 1) downloadData(position);
....
}
But it does not work, the new data is loaded but does not add to top
Since I'm doing this for the first time, maybe I did not choose the right approach.
If you did this, tell how to create a news feed correctly.
If you don't have a updated field by which you can do
findAllSortedAsync("updated", Sort.DESCENDING)
Then you might want to consider adding a RANK field, and sort based on that.
For example,
// when downloading new items by "SwipeToRefresh" from top
// inside Realm transaction
RealmResults<FeedItem> feedItems = dao.findAll(realm);
for(int i = feedItems.size() - 1; i >= 0; i--) {
FeedItem feedItem = feedItems.get(i);
feedItem.setRank(feedItem.getRank() + response.size());
}
long rank = 1;
FeedItem defaultInstance = new FeedItem();
for(FeedItemDTO dto : response) {
FeedItem realmObject = mapper.toRealmObject(realm, dto, defaultInstance);
realmObject.setRank(rank++);
dao.insertOrUpdate(realm, realmObject);
}
And
// when download new items by scrolling to bottom
// inside Realm transaction
long count = dao.count(realm);
long rank = count + 1;
FeedItem defaultInstance = new FeedItem();
for(FeedItemDTO dto : response) {
FeedItem realmObject = mapper.toRealmObject(realm, dto, defaultInstance);
realmObject.setRank(rank++);
dao.insertOrUpdate(realm, realmObject);
}
public FeedItem toRealmObject(Realm realm, FeedItemDTO dto, FeedItemInterface defaultInstance) {
if(defaultInstance == null) {
defaultInstance = new FeedItem();
}
defaultInstance.setId(dto.getId());
RealmList<FeedCategory> categoryIds = new RealmList<FeedCategory>();
if(dto.getCategoryIds() != null) {
for(Long categoryId : dto.getCategoryIds()) {
FeedCategory feedCategory = feedCategoryRepository.findOne(realm, categoryId);
if(feedCategory != null) {
categoryIds.add(feedCategory);
}
}
}
defaultInstance.setCategoryIds(categoryIds);
defaultInstance.setCreatedTime(new Date(dto.getCreatedTime()));
defaultInstance.setUpdatedTime(new Date(dto.getUpdatedTime()));
defaultInstance.setTitle(dto.getTitle());
defaultInstance.setShortDescription(dto.getShortDescription());
defaultInstance.setNumberOfLikes(dto.getNumberOfLikes());
defaultInstance.setIsLiked(dto.getIsLiked());
defaultInstance.setIsFavorited(dto.getIsFavorited());
defaultInstance.setIsImportant(dto.getIsImportant());
defaultInstance.setImageUrl(dto.getImageUrl());
defaultInstance.setTypeCode(dto.getTypeCode());
defaultInstance.setResultTypeCode(dto.getResultTypeCode());
return defaultInstance;
}