Firebase:Recyclerview 没有附加适配器,跳过布局
Posted
技术标签:
【中文标题】Firebase:Recyclerview 没有附加适配器,跳过布局【英文标题】:Firebase:Recycler view No Adater attached , Skipping Layout 【发布时间】:2019-07-07 17:40:08 【问题描述】:嘿,我刚开始使用 firebase,到目前为止它很棒。但是,当我尝试使用 Firebase-UI 和 Firebase RecyclerView 将我的数据挂钩到 CardView
时,我收到以下错误:
E/Recyclerview:没有附加适配器:跳过布局
如果有人可以提供帮助,我什至是 stackover 流程的新手,那么它将受到尊重。
**This is MainActivity.java**
package com.example.uploadfirebase;
import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.MimeTypeMap;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.FirebaseApp;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.storage.FirebaseStorage;
import com.google.firebase.storage.OnProgressListener;
import com.google.firebase.storage.StorageReference;
import com.google.firebase.storage.StorageTask;
import com.google.firebase.storage.UploadTask;
import com.squareup.picasso.Picasso;
public class MainActivity extends AppCompatActivity
private static final int PICK_IMAGE_REQUEST =1;
private Button mButtonChooseImage;
private Button mButtonUpload;
private TextView mTextViewShowUploads;
private EditText mEditTextFileName;
private ImageView mImageView;
private ProgressBar mProgressBar;;
private Uri mImageUri;
private StorageReference mStorageRef;
private DatabaseReference mDatabaseRef;
private StorageTask muploadtask;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
mButtonChooseImage =findViewById( R.id.button_choose_image );
mButtonUpload=findViewById( R.id.button_upload );
mTextViewShowUploads=findViewById( R.id.text_view_show_upload );
mEditTextFileName=findViewById( R.id.edit_text_file_name );
mImageView =findViewById( R.id.image_view );
mProgressBar=findViewById( R.id.progress_bar );
FirebaseApp.initializeApp( this );
mStorageRef = FirebaseStorage.getInstance().getReference("uploads ");
mDatabaseRef= FirebaseDatabase.getInstance().getReference("uploads");
mButtonChooseImage.setOnClickListener( new View.OnClickListener()
@Override
public void onClick(View v)
openFileChooser();
);
mButtonUpload.setOnClickListener( new View.OnClickListener()
@Override
public void onClick(View v)
if(muploadtask !=null && muploadtask.isInProgress())
Toast.makeText( MainActivity.this,"upload in progress",Toast.LENGTH_SHORT ).show();
else
uploadFile();
);
mTextViewShowUploads.setOnClickListener( new View.OnClickListener()
@Override
public void onClick(View v)
OpenImagesActivity();
);
private void openFileChooser()
Intent intent=new Intent( );
intent.setType("image/*" );
intent.setAction( intent.ACTION_GET_CONTENT );
startActivityForResult( intent,PICK_IMAGE_REQUEST );
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data)
super.onActivityResult( requestCode, resultCode, data );
if(requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK
&& data !=null && data.getData()!=null)
mImageUri=data.getData();
Picasso.with( this ).load(mImageUri).into(mImageView);
private String getfileExtension(Uri uri)
ContentResolver cr=getContentResolver();
MimeTypeMap mime= MimeTypeMap.getSingleton();
return mime.getExtensionFromMimeType( cr.getType( uri ) );
private void uploadFile()
if (mImageUri != null)
StorageReference fileReference =mStorageRef.child( System.currentTimeMillis() +"."+ getfileExtension( mImageUri ) );
muploadtask= fileReference.putFile( mImageUri )
.addOnSuccessListener( new OnSuccessListener<UploadTask.TaskSnapshot>()
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot)
Handler handler=new Handler( );
handler.postDelayed( new Runnable()
@Override
public void run()
mProgressBar.setProgress( 0 );
,5000 );
Toast.makeText( MainActivity.this,"upload successfull",Toast.LENGTH_LONG ).show();
upload upload=new upload(mEditTextFileName.getText().toString().trim(),
taskSnapshot.getMetadata().getReference().getDownloadUrl().toString());
String uploadId=mDatabaseRef.push().getKey();
mDatabaseRef.child( uploadId ).setValue( upload );
)
.addOnFailureListener( new OnFailureListener()
@Override
public void onFailure(@NonNull Exception e)
Toast.makeText( MainActivity.this,e.getMessage(),Toast.LENGTH_SHORT ).show();
)
.addOnProgressListener( new OnProgressListener<UploadTask.TaskSnapshot>()
@Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot)
double progress =(100.0 * taskSnapshot .getBytesTransferred() / taskSnapshot.getTotalByteCount());
mProgressBar.setProgress((int) progress );
);
else
Toast.makeText( this,"no file is selected",Toast.LENGTH_SHORT ).show();
private void OpenImagesActivity()
Intent intent=new Intent( this,ImagesActivity.class );
startActivity( intent );
这是我的 Upload.java
package com.example.uploadfirebase;
public class upload
// contains name and url
private String mName;
private String mImageUrl;
public upload()
// empty constr needed
public upload(String name ,String imageUrl)
if(name.trim().equals(""))
name="No Name";
mName=name;
mImageUrl=imageUrl;
public String getName()
return mName;
public void setName(String name)
mName = name;
public String getImageUrl()
return mImageUrl;
public void setImageUrl(String imageUrl)
mImageUrl = imageUrl;
这是我的 ImageAdapter.java
package com.example.uploadfirebase;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.List;
public class ImageAdapter extends RecyclerView.Adapter <ImageAdapter.ImageviewHolder>
private Context mContext;
private List<upload> mUploads;
private OnItemClickListner mListner;
public ImageAdapter (Context context,List<upload> uploads)
mContext=context;
mUploads=uploads;
@NonNull
@Override
public ImageviewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i)
View v= LayoutInflater.from( mContext ).inflate( R.layout.image_item,parent,false );
return new ImageviewHolder( v );
@Override
public void onBindViewHolder(@NonNull ImageviewHolder imageviewHolder, int position)
upload uploadCurrent =mUploads.get(position);
imageviewHolder.textviewName.setText( uploadCurrent.getName() );
Picasso.with(mContext)
.load( uploadCurrent.getImageUrl() )
.placeholder( R.mipmap.ic_launcher )
.fit()
.centerCrop()
.into( imageviewHolder.imageView );
@Override
public int getItemCount()
return mUploads.size();
public class ImageviewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,
View.OnCreateContextMenuListener , MenuItem.OnMenuItemClickListener
public TextView textviewName;
public ImageView imageView;
public ImageviewHolder(@NonNull View itemView)
super( itemView );
textviewName=itemView.findViewById( R.id.text_view_name );
imageView=itemView.findViewById( R.id.image_view_upload);
itemView.setOnClickListener( this );
itemView.setOnCreateContextMenuListener( this );
@Override
public void onClick(View v)
if (mListner !=null )
int position=getAdapterPosition();
if (position != RecyclerView.NO_POSITION)
mListner.onItemClick( position );
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
menu.setHeaderTitle( "select Action" );
MenuItem doWhatever = menu.add( Menu.NONE,1,1,"Do Whatever");
MenuItem delete = menu.add( Menu.NONE,2,2,"Delete" );
doWhatever.setOnMenuItemClickListener( this );
delete.setOnMenuItemClickListener( this );
@Override
public boolean onMenuItemClick(MenuItem item)
if (mListner !=null )
int position=getAdapterPosition();
if (position != RecyclerView.NO_POSITION)
switch (item.getItemId())
case 1:
mListner.onWhateverClick( position );
return true;
case 2:
mListner.OndeleteClick( position );
return true;
return false;
public interface OnItemClickListner
void onItemClick (int Position);
void onWhateverClick (int Position);
void OndeleteClick(int Position);
public void setOnItemClickListner (OnItemClickListner listner)
mListner=listner;
这是我的 ImagesActivty.java
package com.example.uploadfirebase;
import android.support.annotation.NonNull;
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.ProgressBar;
import android.widget.Toast;
import com.google.firebase.FirebaseApp;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.List;
public class ImagesActivity extends AppCompatActivity implements ImageAdapter.OnItemClickListner
private RecyclerView mRecyclerView;
private ImageAdapter mAdapter;
private DatabaseReference mDatabaseRef;
private List <upload> mUploads;
private ProgressBar mProgressCircle;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_images );
mRecyclerView=findViewById( R.id.recycler_view );
mRecyclerView.setHasFixedSize( true );
mRecyclerView.setLayoutManager( new LinearLayoutManager( this ) );
mProgressCircle =findViewById( R.id.progress_cirle );
mUploads = new ArrayList<>( );
FirebaseApp.initializeApp( this );
mDatabaseRef = FirebaseDatabase.getInstance().getReference("uploads");
mDatabaseRef.addValueEventListener( new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
for (DataSnapshot postSnapshot:dataSnapshot.getChildren())
// upload with small u is my class and activty name
// upload with big u is my object name and paremter showld be passed with Big Uploads
upload Upload=postSnapshot.getValue(upload.class);
mUploads.add( Upload );
mAdapter=new ImageAdapter( ImagesActivity.this,mUploads );
mRecyclerView.setAdapter( mAdapter );
mAdapter.setOnItemClickListner( ImagesActivity.this );
mProgressCircle.setVisibility( View.INVISIBLE );
@Override
public void onCancelled(@NonNull DatabaseError databaseError)
Toast.makeText( ImagesActivity.this,databaseError.getMessage(),Toast.LENGTH_SHORT ).show();
mProgressCircle.setVisibility( View.INVISIBLE );
);
@Override
public void onItemClick(int Position)
Toast.makeText( this,"normal click "+ Position, Toast.LENGTH_SHORT ).show();
@Override
public void onWhateverClick(int Position)
Toast.makeText( this,"whatever click "+ Position, Toast.LENGTH_SHORT ).show();
@Override
public void OndeleteClick(int Position)
Toast.makeText( this,"delete click "+ Position, Toast.LENGTH_SHORT ).show();
【问题讨论】:
【参考方案1】:要解决这个问题,请将适配器设置在回调外部和内部,只需将更改通知它即可:
mAdapter = new ImageAdapter(ImagesActivity.this,mUploads);
mRecyclerView.setAdapter(mAdapter);
mDatabaseRef.addValueEventListener( new ValueEventListener()
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot)
for (DataSnapshot postSnapshot:dataSnapshot.getChildren())
// upload with small u is my class and activty name
// upload with big u is my object name and paremter showld be passed with Big Uploads
upload Upload=postSnapshot.getValue(upload.class);
mUploads.add( Upload );
mAdapter.notifyDataSetChanged();
@Override
public void onCancelled(@NonNull DatabaseError databaseError)
Toast.makeText( ImagesActivity.this,databaseError.getMessage(),Toast.LENGTH_SHORT ).show();
mProgressCircle.setVisibility( View.INVISIBLE );
);
【讨论】:
嗨萨加尔!您是否尝试过我上面的解决方案?如果您认为我的回答对您有所帮助,请考虑通过单击左侧投票箭头下方的复选标记(✔️)来接受它。应将颜色更改为绿色。我会很感激的。谢谢!【参考方案2】:这是因为您的适配器正在 valueEventListener 回调中设置。
使用空列表创建适配器并在调用数据库之前对其进行设置。 在您的 valueEventListener 回调中,填充您的上传列表并调用 mAdapter.notifyDataSetChanged();
【讨论】:
【参考方案3】:使用下一行
mAdapter.notifyDataSetChanged();
在你的代码之后
mRecyclerView.setAdapter( mAdapter );
【讨论】:
以上是关于Firebase:Recyclerview 没有附加适配器,跳过布局的主要内容,如果未能解决你的问题,请参考以下文章
Firebase:RecyclerView 跳过布局没有附加适配器
RecyclerView没有被来自firebase的项目填充,只是一个空白的活动页面。
Recyclerview 不会从 firebase 检索数据
将数据从 Firebase 提取到 RecyclerView 时出错。致命异常:...没有定义无参数构造函数