android - 使用 Android 和 Firebase 显示图片列表

标签 android firebase firebase-realtime-database

在回答我的问题之前,先简单介绍一下我的项目,这样您就可以了解所有内容的要点。 我目前正在使用 android 和 Firebase 开发这个房地产应用程序。我一直在使用 Firebase 来存储我的应用程序数据并验证用户身份。 我可以将房地产对象添加到数据库并在 ListView 中检索所有添加的房地产。当我点击一个列表项时,我得到了更详细的不动产版本。房地产的详细信息显示在四个不同的选项卡中。在其中一个选项卡中,我为用户提供了向房地产添加图片等附件的机会。 我添加了添加图片的功能就好了。它们存储在数据库中,如以下屏幕截图所示。

eBncv5ke05ZxR32AiRoP9gSyPkO2 是 user_id 和 “-L38Qe8GEo33i5roKOCi”房地产 ID。键是图像的名称,值是 url。

这是显示我如何将图片添加到数据库的代码:

private void saveImage() {

    // get the expose id
    bundle = getArguments();
    immoID = bundle.getString("exposeID");
    Toast.makeText(getContext(), immoID, Toast.LENGTH_SHORT).show();


    // get an reference to the current user and his id
    user = FirebaseAuth.getInstance().getCurrentUser();
    user_id = user.getUid();

    imageName = imageNameInput.getText().toString();

    if (!TextUtils.isEmpty(imageName)) {

        //displaying progress dialog while image is uploading
        final ProgressDialog progressDialog = new ProgressDialog(getContext());
        progressDialog.setTitle("Bild wird hochgeladen");
        progressDialog.show();



        // uploading the Picture
        pictureStorageRef = FirebaseStorage.getInstance().getReference(user_id).child(Constants.STORAGE_PATH_UPLOADS).child(immoID);
        pictureDataRef = FirebaseDatabase.getInstance().getReference(Constants.DATABASE_PATH_UPLOADS).child(user.getUid()).child(immoID);
        //checking if file is available
        if (filePath != null) {


            //getting the storage reference
            StorageReference sRef = pictureStorageRef.child(Constants.STORAGE_PATH_UPLOADS + System.currentTimeMillis() + "." + getFileExtension(filePath));

            //adding the file to reference
            sRef.putFile(filePath)
                    .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {


                            String imageName = imageNameInput.getText().toString().trim();
                            String imageDownloadURL = taskSnapshot.getDownloadUrl().toString();

                            //creating the upload object to store uploaded image details
                            PictureUpload upload = new PictureUpload(imageName, imageDownloadURL);


                            //adding an upload to firebase database
                            pictureDataRef.child(imageName).setValue(imageDownloadURL);
                            string_immo_image_url = imageDownloadURL;


                            //dismissing the progress dialog
                            progressDialog.dismiss();

                            changeFragment();


                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception exception) {
                            progressDialog.dismiss();
                            Toast.makeText(getContext(), exception.getMessage(), Toast.LENGTH_LONG).show();
                        }
                    })
                    .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
                            //displaying the upload progress
                            double progress = (100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount();
                            progressDialog.setMessage(((int) progress) + "% wurden hochegeladen");
                        }
                    });
        }
    }else{
        imageNameInput.setError("Geben Sie einen Namen ein");
        imageNameInput.requestFocus();

    }
}

现在我尝试在 ListView 的 Fragment 中使用 Glide 显示图片。因此,我为我的 ListView AttachmentList

添加了一个适配器
public class AttachmentList extends ArrayAdapter <PictureUpload> {

List <PictureUpload> pictureUploads;
DatabaseReference pictureDatabase;
FirebaseUser user;
String userid;
private Activity context;

// Constructor
public AttachmentList (Activity context, List<PictureUpload> pictureUploads){
    super (context, R.layout.layout_expose_list, pictureUploads);
    this.context = context;
    this.pictureUploads = pictureUploads;

}

@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
    // inflate the custom layout for the listitems
    LayoutInflater inflater= context.getLayoutInflater();
    final View listViewItem = inflater.inflate(R.layout.layout_expose_list, null, true);

    // get the data item for this position
    PictureUpload pictureUpload = pictureUploads.get(position);


    user = FirebaseAuth.getInstance().getCurrentUser();
    userid = user.getUid();


    // get references to the view elements in the layout for populating the data
    TextView textViewTitle = listViewItem.findViewById(R.id.imageNameDisplay);
    ImageView attachmentImage = listViewItem.findViewById(R.id.attachmentImage);


    // set the most relevant information of the immo object to the textviews
    textViewTitle.setText(pictureUpload.getName());

    Glide.with(getContext()).load(pictureUpload.getUrl()).into(attachmentImage);


    // return the listview item to render
    return listViewItem;
}
}

PictureUpload 类如下所示:

public class PictureUpload {

public String name;
public String url;

// Default constructor required for calls to
// DataSnapshot.getValue(User.class)
public PictureUpload() {
}

public PictureUpload(String name, String url) {
    this.name = name;
    this.url = url;
}

public String getName() {
    return name;
}

public String getUrl() {
    return url;
}
}

这是我试图显示列表的 fragment 的代码:

package com.webgalaxie.blischke.bachelortakesix.fragments.tabfragments;



public class AttachmentTabFragment extends Fragment {
private static final String TAG = "ATTACHMENT_TAB";

FirebaseUser user;
String user_id;

Bundle bundle, newBundle;
String immoID;

// Button to add Attachments to the Expose
Button addAtachments;

private DatabaseReference immoDataRef, pictureDataRef, contactDataRef;
private StorageReference pictureStorageRef;


ListView show_all_attachments_list;
List<PictureUpload> pictureUploads;

public AttachmentTabFragment() {
    // Required empty public constructor
}


// Inflate the view for the fragment based on layout XML
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_attachment_tab, container, false);

    // get reference to the view elements
    addAtachments = view.findViewById(R.id.addAtachments);
    show_all_attachments_list = view.findViewById(R.id.show_all_attachments_list);


    // get the current user
    user = FirebaseAuth.getInstance().getCurrentUser();
    user_id = user.getUid();


    // get the expose id
    bundle = getArguments();
    immoID = bundle.getString("exposeID");

    // set the on ClickListener to the addAttachments Button
    addAtachments.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // change the fragment
            Fragment addAttachmentFragment = new AddAttachmentFragment();
            FragmentManager manager = getFragmentManager();
            newBundle = new Bundle();
            newBundle.putString("exposeID", immoID);
            addAttachmentFragment.setArguments(newBundle);
            manager.beginTransaction().replace(R.id.content_frame, addAttachmentFragment).addToBackStack(null).commit();

        }
    });

    // get reference to the database and storage
    immoDataRef = FirebaseDatabase.getInstance().getReference(Constants.DATABASE_PATH_IMMOBILIEN).child(user_id).child(immoID);
    pictureDataRef = FirebaseDatabase.getInstance().getReference(Constants.DATABASE_PATH_UPLOADS).child(user_id).child(immoID);
    contactDataRef = FirebaseDatabase.getInstance().getReference(Constants.DATABASE_PATH_CONTACTS).child(user_id).child(immoID);
    pictureStorageRef = FirebaseStorage.getInstance().getReference(user_id).child(Constants.STORAGE_PATH_UPLOADS);


    //return the view
    return view;
}

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.showexposemenu, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    final FragmentManager manager = getFragmentManager();
    // get the expose id
    bundle = getArguments();
    immoID = bundle.getString("exposeID");


    switch (item.getItemId()) {
        case R.id.edit_expose:
            Toast.makeText(getContext(), "Expose bearbeiten geklickt.", Toast.LENGTH_SHORT).show();

            // put the immoID into new Bundle
            newBundle = new Bundle();
            newBundle.putString("exposeID", immoID);
            // get a new instance of editExposeFragment
            Fragment editExpose = new EditExposeFragment();
            // set the newBundle as Arguments to the fragement
            editExpose.setArguments(newBundle);
            // switch the fragment
            manager.beginTransaction().replace(R.id.content_frame, editExpose).commit();

            break;
        case R.id.delete_expose:
            Toast.makeText(getContext(), "Expose wurde gelöscht.", Toast.LENGTH_SHORT).show();

            immoDataRef.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    immoDataRef.removeValue();
                    pictureDataRef.removeValue();
                    contactDataRef.removeValue();

                    Fragment showAllExpose = new ShowAllExposeFragment();
                    manager.beginTransaction().replace(R.id.content_frame, showAllExpose).commit();
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });

            break;

    }
    return super.onOptionsItemSelected(item);
}

@Override
public void onStart() {
    super.onStart();
    // attaching the ValueEventListener
    pictureDataRef.addValueEventListener(new ValueEventListener() {


        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // check if there are values in the database
            if (dataSnapshot.getValue() != null) {

                // clear the list of immos
                pictureUploads.clear();

                for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
                    // getting the immo
                    PictureUpload pictureUpload = postSnapshot.getValue(PictureUpload.class);
                    // adding the immo to the list
                    pictureUploads.add(pictureUpload);
                }

                // creating the List Adapter and add him to the Listview
                final AttachmentList attachmentAdapter = new AttachmentList((Activity) getContext(), pictureUploads);
                show_all_attachments_list.setAdapter(attachmentAdapter);


            }

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {


        }

    });


}
}

当我尝试在我的设备上运行我的应用程序时,我总是收到以下错误:

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.webgalaxie.blischke.bachelortakesix, PID: 14901
                  java.lang.NullPointerException: Attempt to invoke interface method 'void java.util.List.clear()' on a null object reference
                      at com.webgalaxie.blischke.bachelortakesix.fragments.tabfragments.AttachmentTabFragment$3.onDataChange(AttachmentTabFragment.java:191)
                      at com.google.android.gms.internal.zzegf.zza(Unknown Source)
                      at com.google.android.gms.internal.zzeia.zzbyc(Unknown Source)
                      at com.google.android.gms.internal.zzeig.run(Unknown Source)
                      at android.os.Handler.handleCallback(Handler.java:751)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6682)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

有没有人知道为什么会这样。我在这个问题上有点卡住了。

非常感谢您的帮助。如果您需要有关该项目的更多信息,请随时询问。

如果您需要更多信息,我还在 GitHub 上提供了该项目的代码。 GitHub 链接:https://github.com/BexxBl/BachelorTakeSix

最佳答案

那是因为在您的 onStart() 方法中,您正在对尚未初始化的列表调用 clear()。您应该初始化它而不是清除它:

        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // check if there are values in the database
            if (dataSnapshot.getValue() != null) {

                // clear the list of immos
                pictureUploads = new ArrayList();

                for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
                    // getting the immo
                    PictureUpload pictureUpload = postSnapshot.getValue(PictureUpload.class);
                    // adding the immo to the list
                    pictureUploads.add(pictureUpload);
                }

                // creating the List Adapter and add him to the Listview
                final AttachmentList attachmentAdapter = new AttachmentList((Activity) getContext(), pictureUploads);
                show_all_attachments_list.setAdapter(attachmentAdapter);


            }

        }

编辑:快照的值是一个字符串。您还需要获取 key 并将其传递给您的 PictureUpload 类。

String val = postSnapshot.getValue(String.class);
PictureUpload pictureUpload = new PictureUpload(postSnapshot.getKey(), val);
pictureUploads.add(pictureUpload);

关于android - 使用 Android 和 Firebase 显示图片列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48325752/

相关文章:

android - 如何在主 UI 线程之外编程

c# - iOS、Android、Windows 10 移动模拟器是否可用于使用 Visual Studio 2015 开发 Xamarin.Forms?

javascript - Firebase Promise 链在 catch block 中终止

ios - Swift 函数从异步 firebase 调用返回值

javascript - 以对象数组形式检索数据 ||火力基地

android - 如何在Gradle中排除androidx库的所有版本文件?

Android:如何将 Google+ 个人资料图片和封面照片放入抽屉导航

android - Android Firebase实现不正确

javascript - 数据不会加载 firebase.google.com 数据库

ios - 我无法从我的快照中获取数据以加载到我的 tableView 单元格中