2017-02-11 83 views
3

我正在編寫一個應用程序來測試Firebase,用戶可以在其中列出包含圖像的產品。 我的上傳存在問題,因爲儘管圖片存儲在圖片中,但未鏈接到產品(圖像數組未傳遞?),LeakCanary表示存在錯誤。 所有幫助和輸入讚賞。Android Firebase多圖像上傳

這裏是我的產品型號

@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

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"); 
// } 

} 
+0

你是什麼意思「他們沒有鏈接到產品」? –

+0

設置的唯一值是(uid,seller,name,description,city and price),就像我沒有傳遞圖像數組 – Ender

回答

1

試圖理解你的代碼流,我可以看到一兩件事:你的publishProduct方法內部

你應該將代碼(更新Firebase中的childeren)放入addOnSuccessListener,如下所示:

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處聽衆,就像這樣:

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) { 

      } 
}); 

更新

我想你可以嘗試更改數據庫結構,從產品節點中刪除圖像列表,在數據庫中添加一個僅存儲與每個產品關聯的圖像列表的節點:

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

包含他的圖像列表。 imageKey不同於另一個圖像(它可能是例如圖像名稱)。 yourKey可能是userId或與每個產品關聯的密鑰,這取決於數據庫的結構。然後,你可以嘗試使用setValue,而不是updateChildren到您的OnSuccessListener,這樣的事情:

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()); 

         } 
       }); 

希望這有助於!