Recycler Adapter上的非Recycler Fragment调用方法?这甚至可能吗?

时间:2017-07-22 15:37:43

标签: android android-recyclerview fragment listener adapter

真诚地为没有代码道歉,我要去参加婚礼,这要么是邮政编码,要么是解释我的情况。

我搜索过Stack并查看了Recycler Adapter to Fragment(创建了适配器)接口的很多帖子。

Fragment(创建适配器)的少数几个适配器帖子,但它们不是很清楚。

我的情况是这样的:

在主要活动上,当应用程序正在运行时:

1)Fragment Lyrics(创建了设置为Lyric Recycler View的REcycler ADapter)

2)片段麦克风(语音识别麦克风功能和XML图标)。

我想要发生的事情是:

用户激活麦克风并说话,结果数据传递到ADAPTER java文件并激活ADAPTER上的方法,从而在屏幕上对RecyclerView Viewholder进行可视化更改。

是的,我知道这可能是糟糕的架构。这是一个学校项目,我正在学习,而且我已经没时间了。

*到目前为止,我能做些什么*

我已经为适配器激活了预先制作的OnClick listerner(当用户点击View时),并为RecyclerView激活OnScroll(用户滚动,它会激活适配器中导致当前视图更改的方法)。

我已经制作了将麦克风片段中的语音数据通过主要活动传递给歌词片段的界面。

在Main上,我只是创建一个Lyrics Fragment的实例,然后在Lyrics Fragment上调用一个自定义方法来获取语音数据。这样的事情。

LyricsFragment.TakeSpeechData(speech data);

*我的计划是什么...... *

当语音数据到达Lyrics Fragment时,我想我可以写下这样的内容:

MyRecyclerAdapter.SomeMethodOnAdapter (speech data);

此时我会回家。

不起作用

不行。我在这里得到一个空指针异常。方法调用的MyRecyclerAdapter部分为null。我看了那个,不知道如何解决它。

我假设我正在引用Fragment放下RecyclerView并设置所有内容时创建的原始适配器。它是Fragment Lyrics上的Adapter的全局变量,我假设它“存在”。

我确信我缺少基本的Java原则,但我不知道是什么。

我花了好几个小时来尝试,阅读,研究。我完全陷入了困境。请帮忙。

编辑:这是我的VerseFragment代码(我在帖子中将其称为“歌词”片段)。请注意,此片段是在屏幕上使用recyclerView加载,创建和运行的。在用户使用也在屏幕上的micrphone片段之前,已经创建了这个片段。

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);
            }
        });
    }
}

从适配器调用方法时,MyRecyclerAdapter是实例还是类?要调用someMethodOnAdpater(speechData),您必须使用实例。夏正在使用一个实例。

如果需要从创建它的片段中调用适配器方法,可以将它存储在这样的变量中。

MyRecyclerAdapter adapter;

@Override
public View onCreateView(...) {
    ...
    adapter = new MyRecyclerAdapter();
    myRecyclerView.setAdapter(adapter);
    ...
}

public void takeSpeechData(String data) {
    adapter.someMethodAdapter(data);
}

修改

我不确定为什么你的recyclerview使用的同一个适配器在设置后为null。绝对可以调用适配器(I tested a basic example)。但是,我的示例中的代码与您之前所说的没有区别。我提出了你的可见度问题。

**编辑:添加Mic Fragment,它有界面**

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,实现CheckSpeech接口

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,我尝试调用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());
            }
        });
    }

1 个答案:

答案 0 :(得分:0)

如果需要从创建它的片段中调用适配器方法,可以将其存储在该片段中的变量中。

MyRecyclerAdapter adapter;

@Override
public View onCreateView(...) {
    ...
    adapter = new MyRecyclerAdapter();
    myRecyclerView.setAdapter(adapter);
    ...
}

public void takeSpeechData(String data) {
    adapter.someMethodAdapter(data);
}

然后你可以直接从另一个片段调用该方法。 (link to accessing fragments)

VersesList versesList = (VersesList) getActivity().getSupportFragmentManager.findFragmentById(containerId);
versesList.takeSpeechData("data");

gif of example