Reputation: 11
Hey I just started out with firebase and its been great so far. However when I try to hook my data in CardView
using Firebase-UI and Firebase RecyclerView, I get the following error:
E/Recyclerview:No Adapter attached :skipping layout
I am even new on stackover flow if any one can help then it will be honored.
**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 );
}
}
this is my 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;
}
}
this is my 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;
}
}
this is my 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();
}
}
Upvotes: 1
Views: 261
Reputation: 138969
To solve this, set the adapter outside the callback and inside it, just notify it about the changes:
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 );
}
});
Upvotes: 2
Reputation: 41
It's because your adapter is being set in the valueEventListener callback.
Create the adapter with an empty list and set it before calling the database. In your valueEventListener callback, populate your uploads list and call mAdapter.notifyDataSetChanged();
Upvotes: 0
Reputation: 771
Use below line
mAdapter.notifyDataSetChanged();
after this in your code
mRecyclerView.setAdapter( mAdapter );
Upvotes: -1