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 时出错。致命异常:...没有定义无参数构造函数

将数据从 Firebase 提取到 RecyclerView 时出错。致命异常:...没有定义无参数构造函数

通过kotlin ..通过firebase从数据库读取数据到RecyclerView的麻烦