【问题标题】:How to structure data in firebase database as a List<String>?如何将 firebase 数据库中的数据构造为 List<String>?
【发布时间】:2018-11-12 03:25:47
【问题描述】:

我想知道如何在 Firebase 数据库中构造我的数据,以便在查询时返回 List&lt;String&gt;。我正在实现一个图像滑块,我需要 Firebase 返回一个包含图像 url 的列表,实现 Parcelable 的模型类可以解析。

这是我的模型类

public class Property implements Parcelable {
private int price;
private String address;
private int numberOfBed;
private int numberOfBath;
private int numberOfCar;
private List<String> propertyImage= new ArrayList<>();
private float lotDim;

public Property() { } //Needed for Firebase's auto data mapping

public Property(int price, String address, int numberOfBed, int numberOfBath,
                int numberOfCar, List<String> propertyImage, float lotDim) {
    this.price = price;
    this.address = address;
    this.numberOfBed = numberOfBed;
    this.numberOfBath = numberOfBath;
    this.numberOfCar = numberOfCar;
    this.propertyImage = propertyImage;
    this.lotDim = lotDim;
}

protected Property(Parcel in) {
    price = in.readInt();
    address = in.readString();
    numberOfBed=in.readInt();
    numberOfBath = in.readInt();
    numberOfCar = in.readInt();
    in.readStringList(propertyImage);
    lotDim = in.readFloat();
}

public static  final Creator<Property> CREATOR = new Creator<Property>() {
    @Override
    public Property createFromParcel(Parcel in) {
        return new Property(in);
    }

    @Override
    public Property[] newArray(int i) {
        return new Property[i];
    }
};

public int getPrice() {
    return price;
}
public void setPrice(int price) {
    this.price = price;
}

public String getAddress() {
    return address;
}

public void setAddress(String address) {
    this.address = address;
}

public int getNumberOfBed() {
    return numberOfBed;
}

public void setNumberOfBed(int numberOfBed) {
    this.numberOfBed = numberOfBed;
}

public int getNumberOfBath() {
    return numberOfBath;
}

public void setNumberOfBath(int numberOfBath) {
    this.numberOfBath = numberOfBath;
}

public int getNumberOfCar() {
    return numberOfCar;
}

public void setNumberOfCar(int numberOfCar) {
    this.numberOfCar = numberOfCar;
}

public List<String> getPropertyImage() {
    return propertyImage;
}

public void setPropertyImage(List<String> propertyImage) {
    this.propertyImage = propertyImage;
}

public float getLotDim() {
    return lotDim;
}

public void setLotDim(float lotDim) {
    this.lotDim = lotDim;
}


@Override
public  int describeContents(){
    return  0;
}

@Override
public void writeToParcel( Parcel dest, int flags){
    dest.writeInt(price);
    dest.writeString(address);
    dest.writeInt(numberOfBed);
    dest.writeInt(numberOfBath);
    dest.writeInt(numberOfCar);
    dest.writeStringList(propertyImage);
    dest.writeFloat(lotDim);
}

}

这是我当前的 Firebase 结构。它实际上返回一个字符串。我希望它返回一个 propertyImage 列表。

这是将使用模型类的片段,这就是我需要实现代码的地方。请注意,在底部,我解决了一些问题,在 firebase 数据库中,我将所有 url 附加到一个字符串中(这是一个肮脏的解决方案),然后拆分 url 将该字符串转换为一个数组。 :-) 那么如何实现@Alex Mano 提供的新代码。谢谢大家

package com.realty.drake.kunuk;

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;

import java.text.NumberFormat;
import java.util.Locale;


/**
* Created by drake on 4/11/18
 */

public class Tab1Buy extends Fragment {
private DatabaseReference propertyRef;
private RecyclerView mPropertyRecyclerView;
FirebaseRecyclerAdapter<Property, PropertyViewHolder> mPropertyAdapter;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.property_tab, container, false);
    mPropertyRecyclerView = rootView.findViewById(R.id.property_recyclerView);
    return rootView;
}


//TODO Check internet and display error msg if internet down
@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    mPropertyRecyclerView.hasFixedSize();
    mPropertyRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    final ProgressBar progressBar = view.findViewById(R.id.progressBar);
    progressBar.setVisibility(View.VISIBLE);

    propertyRef = FirebaseDatabase.getInstance()
            .getReference()
            .child("Buy");
    propertyRef.keepSynced(true);

    // keyQuery - the Firebase location containing the list of keys to be found in dataRef
    //Query personQuery = personRef.orderByKey();


    FirebaseRecyclerOptions<Property> options =
            new FirebaseRecyclerOptions.Builder<Property>()
                    .setQuery(propertyRef, Property.class)
                    .build();

    mPropertyAdapter = new FirebaseRecyclerAdapter<Property, PropertyViewHolder>(options) {


        @Override
        // Bind the Property object to the ViewHolder PropertyHolder
        public void onBindViewHolder(@NonNull PropertyViewHolder holder,
                                     final int position, @NonNull final Property model) {
            holder.setPrice(model.getPrice());
            holder.setAddress(model.getAddress());
            holder.setNumberOfBed(model.getNumberOfBed());
            holder.setNumberOfBath(model.getNumberOfBath());
            holder.setNumberOfCar(model.getNumberOfCar());
            holder.setPropertyImage(model.getPropertyImage());

        //Intent send Parcelable to PropertyDetail
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getActivity().startActivity(new Intent(getActivity(), PropertyDetail.class)
                .putExtra("Property", model));

            }
        });


        }

        @Override
        public PropertyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            // Create a new instance of the ViewHolder, in this case we are using a custom
            // layout called R.layout.property_card for each item
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.property_card, parent, false);
            return new PropertyViewHolder(view);

        }

        @Override
        public void onDataChanged() {
            // Called each time there is a new data snapshot. You may want to use this method
            // to hide a loading spinner or check for the "no documents" state and update your UI.
            // ...
            progressBar.setVisibility(View.GONE);
        }

        //TODO Implement onError
        @Override
        public void onError(@NonNull DatabaseError e) {
            // Called when there is an error getting data. You may want to update
            // your UI to display an error message to the user.
            // ...
            progressBar.setVisibility(View.GONE);
            Toast.makeText(getActivity(), "DatabaseError", Toast.LENGTH_SHORT).show();
        }

    };
    mPropertyRecyclerView.setAdapter(mPropertyAdapter);



}

@Override
public void onStart() {
    super.onStart();
    mPropertyAdapter.startListening();
}

@Override
public void onStop() {
    super.onStop();
    mPropertyAdapter.stopListening();
}


public class PropertyViewHolder extends RecyclerView.ViewHolder {
    View mView;

    public PropertyViewHolder(View itemView) {
        super(itemView);
        mView = itemView;
    }

    public void setPrice(int price) {
        String currencyPrice = NumberFormat //Format the price variable in currency form
                .getCurrencyInstance(Locale.US)
                .format(price);
        TextView Price = mView.findViewById(R.id.post_price);
        Price.setText(currencyPrice);
    }

    public void setAddress(String address){
        TextView Address = mView.findViewById(R.id.post_address);
        Address.setText(String.valueOf(address));
    }

    public void setNumberOfBed(int numberOfBed){
        TextView NumberOfBed = mView.findViewById(R.id.post_bedroom);
        NumberOfBed.setText(String.valueOf(numberOfBed));
    }

    public void setNumberOfBath(int numberOfBath){
        TextView NumberOfBath = mView.findViewById(R.id.post_bathroom);
        NumberOfBath.setText(String.valueOf(numberOfBath));
    }

    public  void  setNumberOfCar(int numberOfCar) {
        TextView NumberOfCar = mView.findViewById(R.id.post_garage);
        NumberOfCar.setText(String.valueOf(numberOfCar));
    }

    public void setPropertyImage(String propertyImage){
        ImageView imageView = mView.findViewById(R.id.post_propertyImage);

        //take one long string containing multiple url in and parse it
        String propertyImageArray[] = propertyImage.split(",");

        //TODO add loading icon for placeholder

        // Download directly from StorageReference using Glide
        // (See MyAppGlideModule for Loader registration)
        GlideApp.with(getContext())
                .load(propertyImageArray[0])
                .fitCenter()
                .into(imageView);
    }
}

}

【问题讨论】:

标签: java android firebase arraylist firebase-realtime-database


【解决方案1】:

假设 Buy 节点是您的 Firebase 根的直接子节点,要解决此问题,请使用以下代码:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference propertyImageRef = rootRef.child("Buy").child("1").child("propertyImage");
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String url = ds.getValue(String.class);
            Log.d("TAG", url);
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
propertyImageRef.addListenerForSingleValueEvent(valueEventListener);

输出将是所有这些 url。

【讨论】:

  • 谢谢@Alex Mamo,我会测试并报告。
  • 太完美了。随时通知我。
  • 代码对我来说有点模棱两可。请原谅我的菜鸟。 'for' 循环会附加 url 还是覆盖先前的值。我的意思是在循环结束时,字符串 url 是否包含所有 url?其实我用的是firebase-ui数据库,你发的代码需要在一个fragment里面上传,我会上传代码
  • 目前只是在包含每个 url 的 logcat 中添加一个新行。不,最后它不会是一个包含所有 url 的字符串。所有网址都是单独的网址。如果需要,可以将它们添加到列表中。
  • 你能看一下我刚刚上传的代码吗?
猜你喜欢
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
  • 2013-05-12
  • 2014-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多