从单独的异步任务类返回数据

3

我在A类中有一个名为Arraylist<image>的图像数组。

我有一个异步任务,它是一个独立的文件。在异步任务中,我填充了一个Arraylist<String> imagePaths,它是通过以下方式在doInBackground中派生的:

for (Image image: images) {
    imagePaths.add(getPath(image));
} 

我想把imagePaths发送到A类,在后台完成后。我想在不传递A类实例到AsyncTask的情况下完成它。 这是我的代码,但我无法从AsyncTask获取imagePath:

public class SellCarInformationActivity extends BaseActivity implements  
        OnWheelChangedListener,
        saveImageAsyncTaskListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Res.init(this);
        setContentView(R.layout.activity_sell_car_information);
        bimap = BitmapFactory.decodeResource(
                getResources(),
                R.drawable.icon_addpic_unfocused);
        PublicWay.activityList.add(this);
        parentView = getLayoutInflater().inflate(R.layout.activity_sell_car_information, null);
        setContentView(parentView);
        //hide editext key board when click other place
        mHideEditor=new HideEditorKeyboard(this);
        mHideEditor.setupUI(findViewById(R.id.sellCarInfromationId));
        carInformationDB=new CarInformationDB(this);
        carPictureUrlDB=new CarPictureUrlDB(this);
        Init();
        eventListener=this;





            }
        });
        mCarPublishBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mCarInformation=new CarInformation();
                mCarInformation.setCarBrand(mBrandText.getText().toString());
                mCarInformation.setCarModel(mModelText.getText().toString());
                mCarInformation.setCarUsedHours(Integer.parseInt(mCarUsedHours.getText().toString()));
                mCarInformation.setCarSite(mSiteText.getText().toString());
                mCarInformation.setCarProducedYear(mCarProduceDateText.getText().toString());
                mCarInformation.setCarPrice(Double.parseDouble(mCarPrice.getText().toString()));
                mCarInformation.setCarUsedState(mCarStateText.getText().toString());
                mCarInformation.setCarUsedPurpose(mCarUsingPurposeText.getText().toString());
                mCarInformation.setCarUserDescriber(mCarDescriber.getText().toString());
                mCarInformation.setCarUserName(mCarUserName.getText().toString());
                mCarInformation.setCarUserPhone(mCarUserPhone.getText().toString());



                //ArrayList<Bitmap> selectedPictures;
                HashMap<String,Bitmap> nameAndPictures=new HashMap<String, Bitmap>();
                String pictureName;
                long j=0;
                for(int i=0;i<Bimp.tempSelectBitmap.size();i++){
                    nameAndPictures.clear();
                   Bitmap selectedPicture= Bimp.tempSelectBitmap.get(i).getBitmap();
                    //selectedPictures=new ArrayList<Bitmap>();
                    //selectedPictures.add(selectedPicture);
                    j=System.currentTimeMillis();
                    j++;

                    pictureName=mModelText.getText().toString()+j;
                    nameAndPictures.put(pictureName,selectedPicture);
                    mCarInformation.setCarPictureLocalName(pictureName);
                }

                long carID=carInformationDB.insertCarInformation(mCarInformation);

                mCarInformation.setCarId((int) carID);

               // SaveImageToMemory saveImageToMemory=new SaveImageToMemory(selectedPicture,pictureName,mCarInformation);
                SaveImageToMemory saveImageToMemory=new SaveImageToMemory(nameAndPictures,mCarInformation);
                saveImageToMemory.setEventListener(eventListener);
                saveImageToMemory.execute();

                storeImagePathstoDB(carID);
                Toast.makeText(SellCarInformationActivity.this,
                        "发布成功"+carInformationDB.getCarInformationByCarId(carID).getCarBrand()+
                                carInformationDB.getCarInformationByCarId(carID).getCarModel()
                        , Toast.LENGTH_SHORT).show();

            }
        });
    }

    public void storeImagePathstoDB(long caID) {
        long carID =caID ;
        userLoadPictureUrl=new UserLoadPictureUrl();
        userLoadPictureUrl.setCarId((int) carID);
        userLoadPictureUrl.setPictureUrl1(imagePaths.get(0));
        userLoadPictureUrl.setPictureUrl2(imagePaths.get(1));
        userLoadPictureUrl.setPictureUrl3(imagePaths.get(2));
        userLoadPictureUrl.setPictureUrl4(imagePaths.get(3));
        userLoadPictureUrl.setPictureUrl5(imagePaths.get(4));
        userLoadPictureUrl.setPictureUrl6(imagePaths.get(5));
        userLoadPictureUrl.setPictureUrl7(imagePaths.get(6));
        userLoadPictureUrl.setPictureUrl8(imagePaths.get(7));
        userLoadPictureUrl.setPictureUrl9(imagePaths.get(8));
        carPictureUrlDB.insertUserLoadPictureUrl(userLoadPictureUrl);
        carPictureUrlDB.getUserLoadPictureUrlByCarId(carID);
    }


public class SaveImageToMemory extends AsyncTask< HashMap<String,Bitmap>, Void, ArrayList<String> > {
   Bitmap image;
    String imageName;
    String imagePath;
    CarInformation carInformation;
    HashMap<String,Bitmap> nameAndPicture;
    private Context context = null;
    private ArrayList<String> storePictureUrl;
    private saveImageAsyncTaskListener eventListener;
    private ArrayList<String> imagePaths;
    public SaveImageToMemory(HashMap<String,Bitmap> nameAndPicture, CarInformation carInformation) {
        super();
       // this.image = image;
       // this.imageName = imageName;
        this.carInformation = carInformation;
        this.nameAndPicture=nameAndPicture;
    }

    @Override
    protected ArrayList<String> doInBackground(HashMap<String,Bitmap>... params) {
        HashMap<String,Bitmap> nameAndPicture=params[0];
        imagePaths = new ArrayList<String>();
        storePictureUrl= new ArrayList<>();
        for(Map.Entry<String,Bitmap> entry :nameAndPicture.entrySet()){
             imageName=entry.getKey();
             image=entry.getValue();
            imagePath = saveImageInternalMemory(image, imageName);
            imagePaths.add(imagePath+ "/" +imageName);
        }


        return imagePaths;
    }

    @Override
    protected void onPostExecute(ArrayList<String> result) {
        Log.d("News reader", "Feed downloaded");
        eventListener.onImagePathsReady(imagePaths);
       // carInformation.setCarPictureLocalUrl(imagePath);
       // saveToDatabase(carInformation, imagePath);
    }

    public String saveImageInternalMemory (Bitmap bitmapImage, String imageName){
        ContextWrapper cw = new ContextWrapper(AppController.getInstance().getApplicationContext());
        // path to /data/data/yourapp/app_data/imageDir
        File directory = cw.getDir("imageDir", Context.MODE_PRIVATE);
        // Create imageDir
        File mypath=new File(directory, imageName);
        FileOutputStream fos = null;
        try {

            fos = new FileOutputStream(mypath);
            // Use the compress method on the BitMap object to write image to the OutputStream
            bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
            fos.close();


        } catch (Exception e) {
            e.printStackTrace();
        }
        return directory.getAbsolutePath();
    }

    public void setEventListener(saveImageAsyncTaskListener listener){
        this.eventListener=listener;
    }

}

1
你尝试过使用“接口”吗? - Emil
将类A的实例传递到异步任务中有什么问题? - Nir Alfasi
2个回答

2

使用自定义事件是最好的方法。当异步任务完成创建ArrayList<String> imagePaths时,您的类A需要触发一个事件。

在Android中,可以使用接口来创建自定义事件。

这应该是类A

Class A  implements MyAsyncTaskListenerInterface{

 private ArrayList<image> images = getImages();  // array with 9 images
 private ArrayList<String> imagePaths; // array to store image 9 paths

 private void someMethod() {
   MyAsyncTask asyncTask = new AsyncTask();
   asyncTask.setEventListener(this);
   asyncTask.execute(images);
 }

 @Override
 onPathsReady(ArrayList<String> paths) {
  this.imagepaths =  paths;
 }

}

这应该是MyAsyncTask

public MyAsyncTask extends Asynctask<ArrayList<image>, Void, Void> {
   private MyAsyncTaskListenerInterface eventListener;

   @Override
   DoInBackground(ArrayList<image>... params) {
     ArrayList<Image> images = params[0];
     ArrayList<String> imagePaths = new ArrayList<String>();

     for (Image image : images) {
       String path = getImagePath(image);
       imagePaths.add(path);
     } 
    eventListener.onPathsReady(imagePaths); 
  }

  public void setEventListener(MyAsyncTaskListenerInterface listener) {
    this.eventListener = listener;
  }

  private String getImagePath(Image image) {
    // your code
  }
}

现在,创建一个类似这样的接口MyAsyncTaskListenerInterface
public interface MyAsyncTaskListenerInterface {
  void onPathsReady(ArrayList<String> paths);
}

最好的做法是为接口创建一个单独的文件。

DoInBackground中,事件在paths数组被创建并传递到事件之后触发。

类A被设置为事件的监听器,onPathsReady(ArrayList<String> paths)方法被触发,您可以按如下所示在该方法中分配值。

使用接口和触发自定义事件是使代码非常干净,更好地利用Java功能的绝佳方法。


你的回答非常清晰,如果我不使用接口,而是使用回调方法,例如在A类中,我编写了一个方法:public void getTheImagePaths(ArrayList<imagePath> imagePaths){this.imagePaths=imagePaths},然后在Async类中,我使用A类对象调用getTheImagePaths(imagePaths)方法,并将imagePath传递给该方法,这样我就可以在A类中获取ImagePaths。 - Gang Luo
你可以这样做,但是这种方式存在一些问题,比如:1)它是非常糟糕的代码。你有一个单独的异步任务类,因为你想使它可重用,但如果你必须传递一个类A的对象,只有类A才能使用异步任务类。此外,我相信这就是你在问题中询问不想传递类A实例到异步任务的原因。你应该使用接口,因为这是最好的方法。接口一开始可能有点令人困惑,但通过复制这段代码并编写代码,你以后会弄清楚它的工作原理。 - rgv
asyncTask.setEventListener(this); “this”是什么? - Gang Luo
在Java中,“this”关键字表示该类的实例。因此,当您在类“A”内部使用“this”时,该类A的实例被传递。 - rgv
你已经定义了setEventListener(MyAsyncTaskListenerInterface listener)函数,参数为MyAsyncTaskListenerInterface类型,然而"this"是A类的实例。我正在使用你的答案,但未能获得结果。 - Gang Luo
当一个类实现了一个接口时,该类就可以作为该接口的类型进行传递。因此,任何实现了 MyAsyncTaskListenerInterface 接口的类的实例都可以传递到这个方法中。如果说“没有得到结果”,那么请进行调试并指定具体的问题所在。 - rgv

0

我想你需要的一切都已经在SO中得到了回答(我在我的答案底部放置了一个链接):

(答案所说的是,你应该有一个继承AsynkTask的类,并调用execute方法,在该类中实现doInBackgorund返回你需要的内容,对于你的情况是一个URL列表)

// This method is not called directly. 
 // It is fired through the use of execute()
 // It returns the third type in the brackets <...>
 // and it is passed the first type in the brackets <...>
 // and it can use the second type in the brackets <...> to track progress
 protected Long doInBackground(URL... urls) 
 {
         int count = urls.length;
         long totalSize = 0;

         // This will download stuff from each URL passed in
         for (int i = 0; i < count; i++) 
         {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
         }

         // This will return once when all the URLs for this AsyncTask instance
         // have been downloaded
         return totalSize;
 }

但是,请务必查看整个答案:

如何在AsyncTasks中传递变量?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接