Reputation: 43
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 . Xia is using an instance.MyRecyclerAdapter
an instance or the class? To call someMethodOnAdpater(speechData)
, you must use 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());
}
});
}
Upvotes: 1
Views: 241
Reputation: 461
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");
Upvotes: 0