我正在尝试通过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:未连接适配器;跳过布局
如果您发现我的代码有问题,请告诉我们,我们将期待您的答复。
答案 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(); }
在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) {
}
});
谢谢