从ListView中单击的Firebase元素中检索信息

时间:2017-12-12 18:17:36

标签: android listview parsing android-fragments firebase-realtime-database

我正在创建一个使用Firebase存储和检索数据的应用。当我检索数据库的数据时,我将它显示在片段中的ListView中。然后我可以单击列表中的给定元素,它会打开一个详细信息片段。 现在,我只能显示来自DB的预定节点的数据,但我想显示我点击的元素的数据。为此,我需要提取节点唯一密钥并将其解析为其他片段,因此可以显示来自所选节点的数据。但我不知道怎么做?你能救我吗?

这是我的数据库结构的图片:

enter image description here

“Song”是数据库中的第一个子项,它是我要提取的-L - ***** ...键。

以下是SongData元素的代码,它是发送到数据库并从数据库中检索的代码:

    public class SongData implements Serializable {

private String songTitel;
private String songArtist;
private String songLanguage;
private String songCode;
private String intentAction;
private int resultCode;

    public SongData(){ }

public SongData(String songTitel, String songArtist){

    this.songTitel = songTitel;
    this.songArtist = songArtist;
}

public SongData(String songTitel, String songArtist, String songLanguages, String songCode){

    this.songTitel = songTitel;
    this.songArtist = songArtist;
    this.songLanguage = songLanguages;
    this.songCode = songCode;
}

public String getSongTitel() {
    return songTitel;
}
public void setSongTitel(String songTitel) {
    this.songTitel = songTitel;
}

public String getSongArtist() {
    return songArtist;
}
public void setSongArtist(String songArtist) {
    this.songArtist = songArtist;
}

public String getSongLanguage() {
    return songLanguage;
}
public void setSongLanguage(String songLanguage) {
    this.songLanguage = songLanguage;
}

public String getSongCode() {
    return songCode;
}
public void setSongCode(String songCode) {
    this.songCode = songCode;
}

public String getIntentAction() {
    return intentAction;
}

public int getResultCode() {
    return resultCode;
}

@Override
public String toString() {
    return "SONG TITLE :" + this.songTitel + "\n SONG ARTIST :" + 
    this.songArtist;
}
    }

此处显示ListView中的数据的活动代码:

    public class SearchFragment extends Fragment {
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_SONG_TITLE = "song title";
private static final String ARG_SECTION_ID = "section_id";

private String mSongTitle; //mParam1
private Button btnSearch;
private TextView txtViewSearch;
private EditText editTextSearch;
private ListView listViewSearch;
private SearchAdaptor searchAdaptor;

//For storing list of songs from DB
private ArrayList<String> songArrayList = new ArrayList<>();

private OnFragmentSearchInteractionListener mListener;

public SearchFragment() {
    // Required empty public constructor
}

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 *
 * @param songTitle Parameter 1.
 * @return A new instance of fragment SearchFragment.
 */
// TODO: Rename and change types and number of parameters
public static SearchFragment newInstance(String songTitle) {
    SearchFragment fragment = new SearchFragment();
    Bundle args = new Bundle();
    args.putString(ARG_SONG_TITLE, songTitle);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mSongTitle = getArguments().getString(ARG_SONG_TITLE);
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_search, container, false);

    //Find elements from view
    btnSearch = (Button) view.findViewById(R.id.btnSearch);
    txtViewSearch = (TextView) view.findViewById(R.id.txtViewSearch);
    editTextSearch = (EditText) view.findViewById(R.id.editTxtSearch);
    listViewSearch = (ListView) view.findViewById(R.id.listViewSearch);

    //Array adapter for Array List with songs
   final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, songArrayList);
   listViewSearch.setAdapter(arrayAdapter);

    FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference songRef = database.getReference("Song");

    songRef.addChildEventListener(new ChildEventListener() {
        @Override
        public void onChildAdded(DataSnapshot dataSnapshot, String s) {

            SongData song = (SongData) dataSnapshot.getValue(SongData.class);
            String songString = String.valueOf(song);
            songArrayList.add(songString);
            arrayAdapter.notifyDataSetChanged();

        }

        @Override
        public void onChildChanged(DataSnapshot dataSnapshot, String s) {
                //Required
        }

        @Override
        public void onChildRemoved(DataSnapshot dataSnapshot) {

            songArrayList.remove(dataSnapshot.getValue(SongData.class));
            arrayAdapter.notifyDataSetChanged();

        }

        @Override
        public void onChildMoved(DataSnapshot dataSnapshot, String s) {
                //Required
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
                //Required
        }
    });

    listViewSearch.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long Id) {
            //position is the index of the item, counts from 0
            //Reference: https://stackoverflow.com/questions/21028786/how-do-i-open-a-new-fragment-from-another-fragment
            SongDetailsFragment songDetailsFragment = new SongDetailsFragment();
            getActivity().getSupportFragmentManager().beginTransaction()
                     .replace(R.id.fragment_placeholder, songDetailsFragment,"findThisFragment")
                     .addToBackStack(null)
                     .commit();
        }
    });

    return view;
}

@Override
public void onResume() {
    super.onResume();

    // Refresh the state of the +1 button each time the activity receives focus.
    /////btnSearch.initialize(PLUS_ONE_URL, PLUS_ONE_REQUEST_CODE);
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnFragmentSearchInteractionListener) {
        mListener = (OnFragmentSearchInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnFragmentSearchInteractionListener");
    }
}

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

/**
 * This interface must be implemented by activities that contain this
 * fragment to allow an interaction in this fragment to be communicated
 * to the activity and potentially other fragments contained in that
 * activity.
 * <p>
 * See the Android Training lesson <a href=
 * "http://developer.android.com/training/basics/fragments/communicating.html"
 * >Communicating with Other Fragments</a> for more information.
 */
public interface OnFragmentSearchInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}

    }

显示详细信息的片段的代码:

    public class SongDetailsFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// The request code must be 0 or greater.
private static final int PLUS_ONE_REQUEST_CODE = 0;
// The URL to +1.  Must be a valid URL.
private final String PLUS_ONE_URL = "http://developer.android.com";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private PlusOneButton mPlusOneButton;

private OnSongDetailsFragmentInteractionListener mListener;

private TextView txtViewShowSongTitel;
private TextView txtViewShowSongArtist;
private TextView txtViewShowSongLanguage;
private TextView txtViewShowSongCode;

public SongDetailsFragment() {
    // Required empty public constructor
}

/**
 * Use this factory method to create a new instance of
 * this fragment using the provided parameters.
 *
 * @param param1 Parameter 1
 * @return A new instance of fragment SongDetailsFragment.
 */
// TODO: Rename and change types and number of parameters
public static SongDetailsFragment newInstance(String param1) {
    SongDetailsFragment fragment = new SongDetailsFragment();
    Bundle args = new Bundle();
    args.putString(ARG_PARAM1, param1);
    fragment.setArguments(args);
    return fragment;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_song_details, container, false);

    final TextView txtViewShowSongTitel = (TextView) view.findViewById(R.id.TxtViewShowSongTitel);
    final TextView txtViewShowSongArtist = (TextView) view.findViewById(R.id.TxtViewShowSongArtist);
    final TextView txtViewShowSongLanguage = (TextView) view.findViewById(R.id.TxtViewShowSongLanguage);
    final TextView txtViewShowSongCode = (TextView) view.findViewById(R.id.TxtViewShowSongCode);

    // Reference: https://firebase.google.com/docs/database/android/read-and-write
    //Retrieve data for the Firebase Database
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference songRef = database.getReference("Song").child("-L-qBD0S742-EQkVvers");

    songRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            SongData s = dataSnapshot.getValue(SongData.class);

            txtViewShowSongTitel.setText(s.getSongTitel());
            txtViewShowSongArtist.setText(s.getSongArtist());
            txtViewShowSongLanguage.setText(s.getSongLanguage());
            txtViewShowSongCode.setText(s.getSongCode());
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

            // Getting songData failed, log a message
            Log.w(TAG, "loadSong:onCancelled", databaseError.toException());
        }
    });

    Button btnOK = (Button) view.findViewById(R.id.btnOK);
    btnOK.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {

            //Close SongDetailsFragment and return to previous fragment
           getActivity().onBackPressed();
        }

    });

    return view;
}

@Override
public void onResume() {
    super.onResume();

    // Refresh the state of the +1 button each time the activity receives focus.
    //mPlusOneButton.initialize(PLUS_ONE_URL, PLUS_ONE_REQUEST_CODE);
}

// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
    if (mListener != null) {
        mListener.onFragmentInteraction(uri);
    }
}

/*@Override
public void onAttach(Context context) {
    super.onAttach(context);
    if (context instanceof OnSongDetailsFragmentInteractionListener) {
        mListener = (OnSongDetailsFragmentInteractionListener) context;
    } else {
        throw new RuntimeException(context.toString()
                + " must implement OnSongDetailsFragmentInteractionListener");
    }
}*/

@Override
public void onDetach() {
    super.onDetach();
    mListener = null;
}

/**
 * This interface must be implemented by activities that contain this
 * fragment to allow an interaction in this fragment to be communicated
 * to the activity and potentially other fragments contained in that
 * activity.
 * <p>
 * See the Android Training lesson <a href=
 * "http://developer.android.com/training/basics/fragments/communicating.html"
 * >Communicating with Other Fragments</a> for more information.
 */
public interface OnSongDetailsFragmentInteractionListener {
    // TODO: Update argument type and name
    void onFragmentInteraction(Uri uri);
}

    }

我希望有人在这里帮助我!

2 个答案:

答案 0 :(得分:1)

使用SongData注释添加新的字符串字段以存储@Exclude类中的歌曲键。排除注释将告知Firebase在保存/检索数据时跳过带注释的字段。

@Exclude
private String key;

public void getKey(){this.key;}
public void setKey(final String key){this.key = key;}
....

在onChildAdded回调中,从DataSnapshot中获取密钥,并将其保存在SongData对象中。

@Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
        SongData song = (SongData) dataSnapshot.getValue(SongData.class);
        song.setKey(dataSnapshot.getKey());
        String songString = String.valueOf(song);
        songArrayList.add(songString);
        arrayAdapter.notifyDataSetChanged();
    }

现在,您可以通过创建一个实例,将歌曲的密钥从选定的SongData对象传递到您的片段:SongDetailFragment.newInstance(selectedSong.getKey())

修改 如下面的@Alex Mamo所述,您还需要从Firebase中获取所有歌曲。现在,您正在指定一个键。因此,你只会得到一首歌。结合他的答案来构建你的列表,然后实例化你的片段。

答案 1 :(得分:1)

要获取所有这些密钥,请使用以下代码:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference songRef = rootRef.child("Song");
ValueEventListener eventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String key = ds.getKey();
            Log.d("TAG", key);
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
songRef.addListenerForSingleValueEvent(eventListener);

输出将是那些生成的密钥。