【问题标题】:Firebase Retrieve Realtime Data With CardviewFirebase 使用 Cardview 检索实时数据
【发布时间】:2017-12-14 13:30:31
【问题描述】:

基本上我正在制作一个应用程序,其中我正在使用 firebase 并尝试检索 real-time database 就像我将图像存储在 firebase storage 并复制“下载 URL”链接并将其粘贴到 firebase 数据库中一样每当我运行我的应用程序时,都应该有一个图像,标题和描述应该出现在该图像下。我基本上想将图像、标题和描述添加到 firebase 数据库并在应用程序中检索。

Activity_main:--

 <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/recyclerview">
        </android.support.v7.widget.RecyclerView>
    </RelativeLayout>

individual_row:-

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">
    <LinearLayout
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:layout_height="wrap_content">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:src="@mipmap/ic_launcher_round"
            android:id="@+id/image"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="#000000"
            android:text="title"
            android:id="@+id/title"/>
        <TextView
            android:layout_width="match_parent"
            android:textColor="#000000"
            android:layout_height="wrap_content"
            android:text="description"
            android:id="@+id/description"/>
    </LinearLayout>
</android.support.v7.widget.CardView>

Firebase 数据库规则:--

{
“规则”:{
".read": "真",
“.write”:“真”
}
}

Firebase 存储规则:--

service firebase.storage {
  match /b/{bucket}/o {
    match[enter image description here][1] /{allPaths=**} {
      // Allow access by all users
      allow read, write;
    }
  }
}

MainActivity:--

package com.namy86.dtunews;

import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.squareup.picasso.Picasso;
public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private DatabaseReference myref;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView=(RecyclerView)findViewById(R.id.recyclerview);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        myref= FirebaseDatabase.getInstance().getReference().child("/blog");
        FirebaseRecyclerAdapter<Blog,BlogViewHolder> recyclerAdapter=new FirebaseRecyclerAdapter<Blog,BlogViewHolder>(
                Blog.class,
                R.layout.individual_row,
                BlogViewHolder.class,
                myref
        ) {
            @Override
            protected void populateViewHolder(BlogViewHolder viewHolder, Blog model, int position) {
                viewHolder.setTitle(model.getTitle());
                viewHolder.setDescription(model.getDescription());
                viewHolder.setImage(model.getImage());
            }
        };
        recyclerView.setAdapter(recyclerAdapter);
    }
    public static class BlogViewHolder extends RecyclerView.ViewHolder {
        View mView;
        TextView textView_title;
        TextView textView_decription;
        ImageView imageView;
        public BlogViewHolder(View itemView) {
            super(itemView);
            mView=itemView;
            textView_title = (TextView)itemView.findViewById(R.id.title);
            textView_decription = (TextView) itemView.findViewById(R.id.description);
            imageView=(ImageView)itemView.findViewById(R.id.image);
        }
        public void setTitle(String title)
        {
            textView_title.setText(title+"");
        }
        public void setDescription(String description)
        {
            textView_decription.setText(description);
        }
        public void setImage(String image)
        {
            Picasso.with(mView.getContext())
                    .load(image)
                    .into(imageView);
        }
    }
}

博客(活动):--

package com.namy86.dtunews;

public class Blog {
    private String title,description,image;
    public Blog() {
    }
    public Blog(String title, String description, String image) {
        this.title = title;
        this.description = description;
        this.image = image;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    public String getImage() {
        return image;
    }
    public void setImage(String image) {
        this.image = image;
    }
}

Firebase 数据库结构:-

demofirebase-1faa

  • 帖子1

    -Description1="First Post"
    -Image1="https://firebasestorage.googleapis.com/v0/b/demofirebase-1faaa.appspot.com/o/Unknown.jpg?alt=media&token=6f5ade3c-d615-4871-90a0-1b4a55e6e00c"
    -Title1="Namy"
    
  • 后2

    -Description2="Second Post"
    -Image2="https://firebasestorage.googleapis.com/v0/b/demofirebase-1faaa.appspot.com/o/Unknown.jpg?alt=media&token=6f5ade3c-d615-4871-90a0-1b4a55e6e00c"
    -Title2="Naman" 
    

【问题讨论】:

  • 请添加您的数据库结构。
  • @AlexMamo 我已经添加了数据库结构
  • 请正确添加。
  • 您到底想知道什么?如何发送数据或如何检索并正确放入卡中?
  • @HugoCastelani 是的,我想知道如何存储数据,然后在应用程序中正确检索或放入

标签: java android firebase firebase-realtime-database


【解决方案1】:

假设您已经正确配置了项目,您可以通过获取引用、创建新节点(正如 Alex Mamo 所说,没有特定节点就无法发送数据)和拟合对象来将数据发送到 firebase在里面。见下文:

// get your reference
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();

// refer your child and use push to generate a new unique node, then put your object
reference.child("blog").push().setValue(blog);

可以通过两种方式加入 firebase 和适配器:在检索对象时显示对象或一次显示所有对象。

逐个对象:

创建一个接收物品的接口:

public interface ItemListener<T> {
    void onItemAdded(@NonNull final T item);
    void onItemRemoved(@NonNull final T item);
}

在您的 DAO 中,创建一个从您的博客节点获取所有对象的方法:

public void getBlogList(@NonNull final ItemListener listener) {
    FirebaseDatabase.getInstance().getReference().child("blog").orderByKey()
        .addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                final Blog blog = dataSnapshot.getValue(Blog.class);
                listener.onItemAdded(blog);
            }

            @Override 
            public void onChildRemoved(DataSnapshot dataSnapshot) {
                final Blog blog = dataSnapshot.getValue(Blog.class);
                listener.onItemRemoved(blog);
            }

            @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
            @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
            @Override public void onCancelled(DatabaseError databaseError) {}
        });
}

在你的适配器中,在构造函数中调用上面的方法,将接收到的博客发送到列表并通知:

public class Adapter extends RecyclerView.Adapter<BlogViewHolder> {
    private List<Blog> mBlogList;

    public Adapter() {  
        getBlogList(new ItemListener<Blog>() {
            @Override
            public void onItemAdded(@NonNull final Blog blog) {
                mBlogList.add(blog);
                notifyItemInserted(mBlogList.size);
            }

            @Override
            public void onItemRemoved(@NonNull final Blog blog) {
                for (Integer i = 0; i < mBlogList.size(); i++) {
                    final Blog innerBlog = mBlogList.get(i);

                    // since you don't store a key, you gotta check all attributes
                    if (innerBlog.getTitle.equals(blog.getTitle) &&
                        innerBlog.getDescription.equals(blog.getDescription) &&
                        innerBlog.getImage.equals(blog.getImage)) {

                        mBlogList.remove(innerBlog);
                        notifyItemRemoved(i);
                   }
                }
            }
        });
    }

    @Override
    public BlogViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new BlogViewHolder(LayoutInflater.from(parent.getContext())
            .inflate(R.layout.individual_row, parent, false));
    }

    @Override
    public void onBindViewHolder(BlogViewHolder holder, int position) {
        final Blog blog = holder.get(position);
        holder.setTitle(blog.getTitle());
        holder.setDescription(blog.getDescription());
        holder.setImage(blog.getImage());
    }

    @Override
    public int getItemCount() {
        return mBlogList.size();
    }
}

一次所有对象:

创建一个接收列表的接口:

public interface ListListener<T> {
    void onListRetrieved(@NonNull final List<T> list);
}

在您的 DAO 中,创建一个从您的博客节点一次获取所有对象的方法:

public void getBlogList(@NonNull final ListListener listener) {
    final List<Blog> blogList = new ArrayList<>();

    FirebaseDatabase.getInstance().getReference().child("blog")
        .addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                for (final DataSnapshot innerDataSnapshot : dataSnapshot.getChildren()) {
                    final Blog blog = innerDataSnapshot.getValue(Blog.class);
                    blogList.add(blog);
                }

                listener.onListRetrieved(blogList);
            }

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

在你的适配器内部,在构造函数中调用上面的方法,克隆接收到的列表并通知:

public class Adapter extends RecyclerView.Adapter<BlogViewHolder> {
    private List<Blog> mBlogList;

    public Adapter() {  
        getBlogList(new ListListener<Blog>() {
            @Override
            public void onListRetrieved(@NonNull final List<Blog> blogList) {
                mBlogList.addAll(blogList);
                notifyDataSetChanged();
            }
        });
    }

    // same code as first Adapter
}

然后,您可以将此适配器添加到您的RecyclerView

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ...
    recyclerView.setAdapter(new Adapter());
}

【讨论】:

  • 我建议为每个代码部分创建一个单独的文件。
【解决方案2】:

您不能将 Image1Image2 等作为 Firebase 数据库中的键。您的密钥在每个节点中必须始终相同。您的数据库应如下所示:

demofirebase-1faa
    |
    --- Post1
    |    |
    |    --- Description: "First Post"
    |    |
    |    --- Image: "https://firebasestorage.googleapis.com/v0/b/demofirebase-1faaa.appspot.com/o/Unknown.jpg?alt=media&token=6f5ade3c-d615-4871-90a0-1b4a55e6e00c"
    |    |
    |    --- Title: "Namy"
    |
    --- Post2
         |
         --- Description: "Second Post"
         |
         --- Image: "https://firebasestorage.googleapis.com/v0/b/demofirebase-1faaa.appspot.com/o/Unknown.jpg?alt=media&token=6f5ade3c-d615-4871-90a0-1b4a55e6e00c"
         |
         --- Title: "Naman"

要根据此数据库模式获取图像,请使用以下代码:

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

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

【讨论】:

  • 我应该在哪里添加这个代码,我应该删除我的一点点原始代码吗? @AlexMamo
  • 这不是复制粘贴代码。这是您需要查询数据库以获得所需结果的方式。但首先,您需要拥有上述架构中的数据库结构。
  • 完成了。问题已解决,实际上我在我的 firebase 数据库中使用了“图像”,而实际上在主要活动中我使用的是“图像”。所以这就是什么都不做的原因。
  • 您认为我的回答对您有帮助吗?
猜你喜欢
  • 1970-01-01
  • 2017-10-06
  • 2020-03-13
  • 1970-01-01
  • 2019-04-16
  • 2020-12-09
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
相关资源
最近更新 更多