Yunter
Yunter

Reputation: 284

Failed to convert value of type java.util.HashMap to String but no hashmap in code?

I am trying to display data that has been added to my Firebase database to android. The data is uploaded to the database fine, but I get the following error when I try to display it through a phone or emulator:

com.google.firebase.database.DatabaseException: Failed to convert value of type java.util.HashMap to String

at the following:

com.firebase.ui.database.FirebaseRecyclerAdapter.parseSnapshot(FirebaseRecyclerAdapter.java:147)

This is the code at line 146 and 147:

protected T parseSnapshot(DataSnapshot snapshot) {
    return snapshot.getValue(mModelClass);
}

This error causes the application to crash and not run. I believe the error is to due with this piece of code in my MainActivity class as when I remove the .child element the app will run, but obviously not display the data.

mDatabase = FirebaseDatabase.getInstance().getReference().child("Blog");

I'm not sure why this error is being thrown as the only data types I have in the database are Strings, and the child "Blog" is spelled correctly in my database.

Another important piece of info: The app will run when I delete the "Blog" child in firebase. However, once I submit data to firebase the error occurs and my app crashes.

Any help would be appreciated,

This class displays the data:

public class MainActivity extends AppCompatActivity {

    private RecyclerView mPostList;
    private DatabaseReference mDatabase;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mDatabase = FirebaseDatabase.getInstance().getReference().child("Blog");

        mPostList = (RecyclerView) findViewById(R.id.post_list);
        mPostList.setHasFixedSize(true);
        mPostList.setLayoutManager(new LinearLayoutManager(this));
    }

    @Override
    protected void onStart() {
        super.onStart();

        FirebaseRecyclerAdapter<Blog, BlogViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Blog, BlogViewHolder>(
                Blog.class,
                R.layout.post_row,
                BlogViewHolder.class,
                mDatabase
                ) {
            @Override
            protected void populateViewHolder(BlogViewHolder viewHolder, Blog model, int position) {

                viewHolder.setTitle(model.getTitle());
                viewHolder.setDesc(model.getDesc());
                viewHolder.setImage(getApplicationContext(), model.getImage());
            }
        };

        mPostList.setAdapter(firebaseRecyclerAdapter);
    }

    public static class BlogViewHolder extends RecyclerView.ViewHolder {

        View mView;

        public BlogViewHolder(View itemView) {
            super(itemView);

            mView = itemView;
        }

        public void setTitle(String title) {
            TextView post_title = (TextView)mView.findViewById(R.id.post_title);
            post_title.setText(title);
        }

        public void setDesc(String desc) {
            TextView post_desc = (TextView)mView.findViewById(R.id.post_desc);
            post_desc.setText(desc);
        }

        public void setImage(Context ctx, String image) {
            ImageView post_image = (ImageView) mView.findViewById(R.id.post_image);
            Picasso.with(ctx).load(image).into(post_image);
        }
    }

    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        if (item.getItemId()== R.id.action_add){
            startActivity(new Intent(MainActivity.this, PostActivity.class));
        }

        return super.onOptionsItemSelected(item);
    }
}

This class posts data to firebase:

package infectionapp.com.infectionui;

public class PostActivity extends AppCompatActivity {

    private ImageButton mSelectImage;
    private Uri  mImageUri = null;
    private EditText mPostTitle;
    private EditText mPostDesc;
    private Button mSubmitBtn;

    private StorageReference mStorage;
    private DatabaseReference mDatabase;

   // private ProgressBar mProgress;
    private static final int GALLERY_REQUEST = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_post);

        //Directs to root firebase storage
        mSelectImage = (ImageButton) findViewById(R.id.imageSelect);

        mStorage = FirebaseStorage.getInstance().getReference();
        mDatabase = FirebaseDatabase.getInstance().getReference().child("Blog");

        mPostTitle = (EditText) findViewById(R.id.titleField);
        mPostDesc = (EditText)findViewById(R.id.descField);
        mSubmitBtn = (Button) findViewById(R.id.submitBtn);

    //    mProgress = new ProgressBar(this);

        mSubmitBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startPosting();

            }
        });

        mSelectImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                Intent galleryIntent = new Intent(Intent.ACTION_GET_CONTENT);
                galleryIntent.setType("image/*");
                startActivityForResult(galleryIntent, GALLERY_REQUEST);
            }
        });
    }

    private void startPosting() {

       final String title_val = mPostTitle.getText().toString().trim();
       final String desc_val = mPostDesc.getText().toString().trim();

        if (!TextUtils.isEmpty(title_val) && !TextUtils.isEmpty(desc_val) && mImageUri != null){
                StorageReference filepath = mStorage.child("Post_Images").child(mImageUri.getLastPathSegment());

                filepath.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

                    Uri downloadUrl = taskSnapshot.getDownloadUrl();

                        //Creates unique ID for post
                        DatabaseReference newPost = mDatabase.push();
                        newPost.child("title").setValue(title_val);
                        newPost.child("desc").setValue(desc_val);
                        newPost.child("image").setValue(downloadUrl).toString();

                        startActivity(new Intent(PostActivity.this, MainActivity.class));
                    }
                });
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == GALLERY_REQUEST && resultCode == RESULT_OK){
            mImageUri = data.getData();
            mSelectImage.setImageURI(mImageUri);

        }
    }
}

Database structure:

Child nodes within children:

Code screenshot

Error of updated code

Upvotes: 0

Views: 951

Answers (1)

Alex Mamo
Alex Mamo

Reputation: 138834

To get that data in the simplest way, i recomand you using this code:

DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference blogRef = rootRef.child("Blog");
ValueEventListener eventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            String desc = ds.child("desc").getValue(String.class);
            String title = ds.child("title").getValue(String.class);
            String image = ds.child("image").child("path").getValue(String.class);
            Log.d("TAG", desc + " / " + title + " / " + image);
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {}
};
blogRef.addListenerForSingleValueEvent(eventListener);

Your output will be:

tst / test / /v0/b/infectionui...

As you see, i have used String class. This is what you need to use also in your FirebaseRecyclerAdapter.

If you want to get antoher value from image, just change .child("path") with another child, let's say .child("schemeSpecificPart").

Upvotes: 1

Related Questions