Android Firebase多个图像上传 [英] Android Firebase multiple image upload

查看:58
本文介绍了Android Firebase多个图像上传的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个应用来测试Firebase,用户可以在其中列出带有图像的产品. 我在上传时遇到问题,因为图片已存储,但未链接到产品(图像数组未传递?),并且LeakCanary发出内存不足错误的信号. 感谢所有帮助和投入.

I am writing an app to test out firebase where a user can list a product with images. I'm having issues with the upload as although the pictures are stored, they are not linked to the product (images array not being passed?) and LeakCanary signals an outofmemory error. All help and input appreciated.

这是我的产品型号

@IgnoreExtraProperties
public class Product {

    public String uid;
    public String seller;
    public String name;
    public String description;
    public String city;
    public double price = 0.0;
    public List<Uri> images = new ArrayList<>();

    public Product () {

    }

    public Product(String uid, String seller, String name, String description, String city, double price, List<Uri> images) {
        this.uid = uid;
        this.seller = seller;
        this.name = name;
        this.description = description;
        this.city = city;
        this.price = price;
        this.images = images;
    }

    // [START post_to_map]
    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put("uid", uid);
        result.put("seller", seller);
        result.put("name", name);
        result.put("description", description);
        result.put("city", city);
        result.put("price", price);
        result.put("images", images);

        return result;
    }
}

这是我的AddProductActivity

And here are is my AddProductActivity

public class AddProductActivity extends BaseActivity implements AddProductContract.View, View.OnClickListener {

    private AddProductContract.Presenter mPresenter;

    private Bitmap mBitmap;
    private byte[] mByteArray;
    private List<String> mPhotos;
    private Button mPublishBtn;
    private EditText mProductNameField;
    private EditText mProductDescriptionField;
    private EditText mProductPriceField;
    private DatabaseReference mFirebaseDatabase;
    private StorageReference mFirebaseStorage;
    private StorageTask mUploadTask;
    private List<Uri> uploadedImages = new ArrayList<>();
    private LinearLayout mLinearLayout;
    private ImageButton mImageButton;

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

        if (data == null) {
            showEmptyImageError();
        } else {
            mPhotos = (List<String>) data.getSerializableExtra(GalleryActivity.PHOTOS);
        }

    }

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

        mFirebaseDatabase = FirebaseDatabase.getInstance().getReference();
        mFirebaseStorage = FirebaseStorage.getInstance().getReference();

        Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(mToolbar);
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);

        mToolbar.setTitle(R.string.addItemTextview);

        mLinearLayout = (LinearLayout) findViewById(R.id.activity_add_product);
        mLinearLayout.setOnClickListener(this);

        mImageButton = (ImageButton) findViewById(R.id.imageButton);
        mImageButton.setOnClickListener(this);

        mPublishBtn = (Button) findViewById(R.id.publishItemBtn);
        mPublishBtn.setOnClickListener(this);

        mProductNameField = (EditText) findViewById(R.id.productNameField);
        mProductDescriptionField = (EditText) findViewById(R.id.productDescriptionField);
        mProductPriceField = (EditText) findViewById(R.id.priceField);

       // mPresenter = new AddProductPresenter(this);
    }

    @Override
    public void onClick(View view) {
        if ((view == mLinearLayout)) {
            hideKeyboard();
        } else if (view == mImageButton) {
            GalleryConfig config = new GalleryConfig.Build()
                    .limitPickPhoto(8)
                    .singlePhoto(false)
                    .hintOfPick("You can pick up to 8 pictures.")
                    .filterMimeTypes(new String[]{"image/*"})
                    .build();
            GalleryActivity.openActivity(AddProductActivity.this, 2, config);
        } else if (view == mPublishBtn) {
            final String name = mProductNameField.getText().toString();
            final String description = mProductDescriptionField.getText().toString();
            final double price = Double.parseDouble(mProductPriceField.getText().toString());
            setPublishingEnabled(false);
            showErrorToast(getResources().getString(R.string.publishing));
            final String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
            mFirebaseDatabase.child("users").child(userId).addListenerForSingleValueEvent(
                    new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            User user = dataSnapshot.getValue(User.class);
                            if (user == null) {
                                showErrorToast(getResources().getString(R.string.empty_user));
                            } else {
                                publishProduct(userId, user.getUsername(), name, description,
                                        user.getCity(), price, mPhotos);
                            }
                            setPublishingEnabled(true);
                            finish();
                        }

                        @Override
                        public void onCancelled(DatabaseError databaseError) {
                            Log.w("AddProductActivity", "getUser:onCancelled", databaseError.toException());
                            setPublishingEnabled(true);
                        }
                    }
            );
        }
    }


    private void setPublishingEnabled(boolean enabled) {
        if (enabled) {
            mPublishBtn.setVisibility(View.VISIBLE);
        } else {
            mPublishBtn.setVisibility(View.GONE);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // handle arrow click here
        if (item.getItemId() == android.R.id.home) {
            finish();
        }

        return super.onOptionsItemSelected(item);
    }


    @Override
    public void showEmptyImageError() {
        Toast.makeText(getApplicationContext(), R.string.empty_image_error, Toast.LENGTH_SHORT).show();
    }

    private void publishProduct(String userId, String seller, String name, String description,
                                String city, double price, List<String> images) {

        for (String photo : images) {
            Uri file = Uri.fromFile(new File(photo));
            StorageReference photoRef = mFirebaseStorage.child("images/" + file.getLastPathSegment());
            mUploadTask = photoRef.putFile(file);

            mUploadTask.addOnFailureListener(exception -> Log.i("It didn't work", "double check"))
                    .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                            Uri downloadUrl = taskSnapshot.getDownloadUrl();
                            uploadedImages.add(downloadUrl);
                        }
                    });
        }


        String key = mFirebaseDatabase.child("products").push().getKey();
        Product product = new Product(userId, seller, name, description, city, price, uploadedImages);
        Map<String, Object> productValues = product.toMap();

        Map<String, Object> childUpdates = new HashMap<>();
        childUpdates.put("/products/" + key, productValues);
        childUpdates.put("/user-products/" + userId + "/" + key, productValues);

        mFirebaseDatabase.updateChildren(childUpdates);
    }

//
//    private List<Uri> uploadPhotos(List<String> input) {
//        images = new ArrayList<>();
//        Observable.just(input)
//                .map(this::doInBackground)
//                .subscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread())
//                .doOnSubscribe(this::onPreExecute)
//                .subscribe(this::onPostExecute);
//        return images;
//    }
//
//    private void onPreExecute() {
//        Log.i("Start time", "SET");
//        Toast.makeText(this, R.string.image_formatting_toast, Toast.LENGTH_SHORT).show();
//    }
//
//    private List<Uri> doInBackground(List<String> photos) {
//        for (String photo : mPhotos) {
//            Uri file = Uri.fromFile(new File(photo));
//            StorageReference photoRef = mFirebaseStorage.child("images/" + file.getLastPathSegment());
//            mUploadTask = photoRef.putFile(file);
//
//            mUploadTask.addOnFailureListener(exception -> Log.i("It didn't work", "double check"))
//                    .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
//                @Override
//                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//                    Uri downloadUrl = taskSnapshot.getDownloadUrl();
//                    images.add(downloadUrl);
//                }
//            });
//        }
//        return  images;
//    }
//
//    private void onPostExecute(List<Uri> uriSet) {
//        Toast.makeText(this, R.string.product_visibility_toast, Toast.LENGTH_SHORT).show();
//        Log.i("End time", "SET");
//    }

}

推荐答案

尝试了解您的代码流,我可以看到一件事:

Trying to understand your code flow, I can see one thing:

在您的publishProduct方法内部,应将代码(以更新Firebase中的childeren)放入addOnSuccessListener中,如下所示:

inside your publishProduct method you should put the code (to update the childeren in Firebase) into the addOnSuccessListener, like this:

private void publishProduct(String userId, String seller, String name, String description,
                            String city, double price, List<String> images) {

    String key = mFirebaseDatabase.child("products").push().getKey();

    for (String photo : images) {
        Uri file = Uri.fromFile(new File(photo));
        StorageReference photoRef = mFirebaseStorage.child("images/" + file.getLastPathSegment());
        mUploadTask = photoRef.putFile(file);

        mUploadTask.addOnFailureListener(exception -> Log.i("It didn't work", "double check"))
                .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        Uri downloadUrl = taskSnapshot.getDownloadUrl();
                        uploadedImages.add(downloadUrl);

                        Product product = new Product(userId, seller, name, description, city, price, uploadedImages);
                        Map<String, Object> productValues = product.toMap();

                        Map<String, Object> childUpdates = new HashMap<>();
                        childUpdates.put("/products/" + key, productValues);
                        childUpdates.put("/user-products/" + userId + "/" + key, productValues);

                        mFirebaseDatabase.updateChildren(childUpdates);
                    }
                });
    }

}

并且,如果您想知道updateChildren操作是否完成,请添加onComplete和onFailure侦听器,如下所示:

And, if you want to know if the updateChildren operation is completed or not, add the onComplete and onFailure listeners, like this:

mFirebaseDatabase.updateChildren(childUpdates).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {

            }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {

            }
});

更新

我认为您可以尝试更改数据库结构,从产品的节点中删除图像列表,而在数据库中添加一个节点,该节点将仅存储与每个产品关联的图像列表:

I think you can try to change your database structure, removing the list of images from the product's nodes, adding instead a node in your database that will store only the list of images associated with each product:

"/product-images/" + yourKey + "/" + imageKey

包含他的图像列表. imageKey与一个图像与另一个图像不同(例如,图像名称). yourKey可以是userId或与每个产品关联的密钥,这取决于数据库的结构.然后,您可以尝试在OnSuccessListener中使用setValue而不是updateChildren,如下所示:

contains the list of his images. imageKey is different from one image the another (it could be for example the image name). yourKey could be the userId or the key associated with each product, it depends on how the database is structured. Then, you can try to use setValue instead of updateChildren into your OnSuccessListener, something like this:

mUploadTask.addOnFailureListener(exception -> Log.i("It didn't work", "double check"))
                    .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                            Uri downloadUrl = taskSnapshot.getDownloadUrl();            

                            mFirebaseDatabase.child("product-images").child(yourKey).child(imageKey).setValue(downloadUrl.toString());

                        }
                });

希望这会有所帮助!

这篇关于Android Firebase多个图像上传的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆