我正在创建一个使用Firebase存储和检索数据的应用。当我检索数据库的数据时,我将它显示在片段中的ListView中。然后我可以单击列表中的给定元素,它会打开一个详细信息片段。 现在,我只能显示来自DB的预定节点的数据,但我想显示我点击的元素的数据。为此,我需要提取节点唯一密钥并将其解析为其他片段,因此可以显示来自所选节点的数据。但我不知道怎么做?你能救我吗?
这是我的数据库结构的图片:
“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);
}
}
我希望有人在这里帮助我!
答案 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);
输出将是那些生成的密钥。