毕加索未将图像从Firebase存储加载到RecyclerView

时间:2019-05-19 17:23:14

标签: android firebase-storage picasso

我正在尝试通过Picasso库从Firebase Storage获取图像,并将其显示在RecyclerView上。

我也尝试过使用其他库(例如Glide和Fresco)加载图像,但是图像仍然没有显示。

请在下面找到该应用程序的代码:

BlogRecyclerAdapter.java:

public BlogRecyclerAdapter(Context context, List<Blog> blogList) {
        this.context = context;
        this.blogList = blogList;
        this.firebaseStorage = firebaseStorage;
    }
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.post_row, parent, false);

        return new ViewHolder(view, context);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        Blog blog = blogList.get(position);
        //String imageUrl = null;

        holder.title.setText(blog.getTitle());
        holder.desc.setText(blog.getDesc());


        DateFormat dateFormat = DateFormat.getDateInstance();
        String formattedDate = dateFormat.format(new Date(Long.valueOf(blog.getTimestamp())).getTime());

        holder.timestamp.setText(formattedDate);

        String imageUrl = blog.getImage();

        //TODO: Use Picasso library to load image

        Picasso.get()
                .load(imageUrl)
                .into(holder.image);
    }

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

    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView title;
        public TextView desc;
        public TextView timestamp;
        public ImageView image;
        String userid;

        public ViewHolder(View view, Context ctx) {
            super(view);


            title = (TextView) view.findViewById(R.id.postTitleList);
            desc = (TextView) view.findViewById(R.id.postTextList);
            image = (ImageView) view.findViewById(R.id.postImageList);
            timestamp = (TextView) view.findViewById(R.id.timestampList);

            userid = null;

            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // we can go to the next activity...

                }
            });

        }
    }
}

PostListActivity.java(在其中显示recyclerView的活动):

public class PostListActivity extends AppCompatActivity {
    private DatabaseReference mDatabaseReference;
    private RecyclerView recyclerView;
    private BlogRecyclerAdapter blogRecyclerAdapter;
    private List<Blog> blogList;
    private FirebaseDatabase mDatabase;
    private FirebaseUser mUser;
    private FirebaseAuth mAuth;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_post_list);

        mAuth = FirebaseAuth.getInstance();
        mUser = mAuth.getCurrentUser();

        mDatabase = FirebaseDatabase.getInstance();
        mDatabaseReference = mDatabase.getReference().child("MBlog");
        mDatabaseReference.keepSynced(true);

        blogList = new ArrayList<>();

        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
            case R.id.action_add:
                if (mUser != null && mAuth != null) {
                    startActivity(new Intent(PostListActivity.this, AddPostActivity.class));
                    finish();
                }
                break;
            case R.id.action_signout:

                if (mUser != null && mAuth != null) {
                    mAuth.signOut();
                    startActivity(new Intent(PostListActivity.this, MainActivity.class));
                    finish();
                }
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onStart() {
        super.onStart();

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

                Blog blog = dataSnapshot.getValue(Blog.class);

                blogList.add(blog);

                Collections.reverse(blogList);


                blogRecyclerAdapter = new BlogRecyclerAdapter(PostListActivity.this, blogList);
                recyclerView.setAdapter(blogRecyclerAdapter);
                blogRecyclerAdapter.notifyDataSetChanged();
            }

            @Override
            public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {

            }

            @Override
            public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {

            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
}

Blog.java(模型):

public class Blog {

    public String title;
    public String desc;
    public String image;
    public String timestamp;
    public String userid;

    public Blog() {
    }

    public Blog(String title, String desc, String image, String timestamp, String userid) {
        this.title = title;
        this.desc = desc;
        this.image = image;
        this.timestamp = timestamp;
        this.userid = userid;
    }


    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public String getTimestamp() {
        return timestamp;
    }

    public void setTimestamp(String timestamp) {
        this.timestamp = timestamp;
    }

    public String getUserid() {
        return userid;
    }

    public void setUserid(String userid) {
        this.userid = userid;
    }
}

post_row.xml:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:layout_margin="5dp">



    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">


        <ImageView
            android:id="@+id/postImageList"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:cropToPadding="false"
            android:scaleType="centerCrop"
            android:src="@mipmap/add_btn"/>


        <TextView
            android:id="@+id/postTitleList"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="10dp"
            android:text="Post Title"
            android:textSize="18sp"
            android:textStyle="bold" />

        <TextView
            android:id="@+id/postTextList"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:paddingTop="15dp"
            android:padding="10dp"
            android:text="Post Description Here"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

        <TextView
            android:id="@+id/timestampList"
            android:text="Date Created"
            android:padding="5dp"
            android:textStyle="italic"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

</android.support.v7.widget.CardView>

activity_post_list.xml:

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.myblogapp.Activities.PostListActivity">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginRight="8dp"
        android:layout_marginLeft="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginBottom="8dp" />
</android.support.constraint.ConstraintLayout>

build.gradle(app):

apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.myblogapp"
        minSdkVersion 16
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }


    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation 'com.android.support:appcompat-v7:28.0.0'
        implementation 'com.android.support.constraint:constraint-layout:1.1.3'
        implementation 'com.google.firebase:firebase-core:16.0.8'
        implementation 'com.google.firebase:firebase-core:16.0.8'
        implementation 'com.google.firebase:firebase-database:16.1.0'
        implementation 'com.firebaseui:firebase-ui-storage:4.3.1'
        implementation 'com.google.firebase:firebase-auth:16.2.0'
        implementation 'com.google.firebase:firebase-storage:16.0.4'
        implementation 'com.github.bumptech.glide:glide:3.7.0'
        testImplementation 'junit:junit:4.12'
        androidTestImplementation 'com.android.support.test:runner:1.0.2'
        androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
        implementation 'com.android.support:recyclerview-v7:28.0.0'
        implementation 'com.android.support:cardview-v7:28.0.0'
        implementation 'com.squareup.picasso:picasso:2.71828'
        implementation 'com.theartofdev.edmodo:android-image-cropper:2.4.+'
        implementation 'com.facebook.fresco:fresco:1.10.0'
        implementation 'com.firebaseui:firebase-ui-storage:4.3.2'
    }


    apply plugin: 'com.google.gms.google-services'
}

在运行代码时,我还遇到了以下错误消息:

E / RecyclerView:未连接适配器;跳过布局

如果您发现我的代码有问题,请告诉我们,我们将期待您的答复。

2 个答案:

答案 0 :(得分:0)

好像您的孩子的列表没有工作。代替ValueEventListener尝试使用ChildEventListener。通过Firebase doc

了解有关侦听器的更多信息
mDatabaseReference.addValueEventListener(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot dataSnapshot) {
    for (DataSnapshot data : dataSnapshot.getChildren()){
       Blog blog = dataSnapshot.getValue(Blog.class);
       blogList.add(blog);
    }
    Collections.reverse(blogList);
    blogRecyclerAdapter = new BlogRecyclerAdapter(PostListActivity.this, blogList);
    recyclerView.setAdapter(blogRecyclerAdapter);
  }

  @Override
  public void onCancelled(DatabaseError databaseError) {
    System.out.println("The read failed: " + databaseError.getCode());
  }
});

答案 1 :(得分:0)

问题在于事件的执行顺序-需要在onCreate()中将适配器设置为回收站视图。毕竟,图像库可能不是问题。

我希望您会理解,很难重现该问题(因为我需要创建一个测试Firebase数据库等),并且100%确定该答案,因此我强烈建议您重新安排适配器代码。

1)将这两行移至PostListActivity中的onCreate()底部:

  blogRecyclerAdapter = new BlogRecyclerAdapter(PostListActivity.this, blogList);
            recyclerView.setAdapter(blogRecyclerAdapter);

2)向BlogRecyclerAdapter类添加一个方法,该方法允许更新设置为适配器的项:

public void updateBlogList(ArrayList<Blog> newBlogs){
this.blogList = newBlogs;
notifyDataSetChanged();  }
  1. 在onChildAdded()方法中,删除上面步骤1中移到onCreate()的三行代码,以便onChildAdded()包含:

    Blog blog = dataSnapshot.getValue(Blog.class);
    
    blogList.add(blog);
    
    Collections.reverse(blogList);
    
    blogRecyclerAdapter.updateBlogList(blogList); 
    

正如我所说,很难重新创建问题,并且代码中可能还有其他问题,但是希望这可以解决“ E / RecyclerView:未连接适配器;跳过布局”错误。

此外,Glide似乎是从外部源加载图像的更强大的库。在我的一个项目中,我能够使用以下代码在适配器的onBind()中加载图像:

 mFirebaseDatabase = FirebaseDatabase.getInstance();
    mRef = mFirebaseDatabase.getReference(Constants.USERS_PATH).child(offeredRoute.getUserID());
    mFirebaseStorage = FirebaseStorage.getInstance();
    mStorageReference = mFirebaseStorage.getReference().child(Constants.IMAGES_PATH).child(offeredRoute.getUserID());

//download all other values
mRef.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
        mUserProfile = dataSnapshot.getValue(UserProfile.class);
        //set data to views
        if (mUserProfile != null) {
            holder.resultUsernameTv.setText(mUserProfile.getUser());

            if (mUserProfile.getPhotoUrl() == null || mUserProfile.getPhotoUrl().isEmpty()) {
                Timber.v("No photo saved yet");
            } else {
                StorageReference downloadRef = mStorageReference.child(mUserProfile.getPhotoUrl());
                Glide.with(mContext)
                        .using(new FirebaseImageLoader())
                        .load(downloadRef)
                        .into(holder.ImageViewRv);
            }
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {

    }
});

谢谢