嘿,我刚开始使用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();
}
}
答案 0 :(得分: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 );
}
});
答案 1 :(得分:0)
这是因为在valueEventListener回调中设置了适配器。
使用空列表创建适配器,并在调用数据库之前进行设置。 在您的valueEventListener回调中,填充您的上传列表,然后调用mAdapter.notifyDataSetChanged();
答案 2 :(得分:-1)
在行下使用
mAdapter.notifyDataSetChanged();
此后在您的代码中
mRecyclerView.setAdapter( mAdapter );