AsyncTask:onPostExecute()在doInBackground()之前运行

时间:2017-08-23 13:03:12

标签: android android-asynctask

以下是从firebase下载文件的asynctask。我在asynctask中使用了一些全局变量。但是从输出中可以清楚地看到onPostExecute()doInBackground()完成之前完成执行。

class downloadTask extends AsyncTask<Void,Void,Void> {

                    @Override
                    protected void onPostExecute(Void aVoid) {
                        for (int i = 0; i < selectedItems.size(); i++) {
                            if (selectedItems.get(i) == 1) {

                                DatabaseReference Ref = FirebaseDatabase.getInstance().getReference("modules").child("items").child(item.getNumber() + "");
                                Ref.removeValue();

                                Log.e("new2","2");
                                Ref.setValue(item);
                                //Log.e("new2",item.getLink());

                                finish();
                            }

                        }
                    }

                    @Override
                    protected Void doInBackground(Void... params) {

                        FirebaseStorage storage = FirebaseStorage.getInstance();
                        StorageReference storageRef = storage.getReference();
                        StorageReference riversRef = storageRef.child("modules/"+mediaUri.getLastPathSegment());
                        UploadTask uploadTask = riversRef.putFile(mediaUri);

                        // Register observers to listen for when the download is done or if it fails
                        uploadTask.addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception exception) {
                                Log.e("download fail","fail");
                            }
                        }).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                            @Override
                            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                                // taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL.
                                Uri downloadUrl = taskSnapshot.getDownloadUrl();
                                fileUrl=downloadUrl.toString();
                                Log.e("new0","fileurl is "+fileUrl);
                                item.setLink(fileUrl);
                                Log.e("new1",item.getLink());


                            }
                        });

                        return null;
                    }
                }

                (new downloadTask()).execute();

在此日志输出中,来自onPostExecute()的日志语句在doInBackground()的日志语句之前打印。因此,我可以说onPostExecute()首先执行。     我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

这是一个错误的假设。 doInBackground()确实在 onPostExecute()之前完成了。问题是,你在doInBackground()中也做了其他的异步内容。因此,一旦添加了OnFailureListener和OnSuccessListener,doInBackground()就会完成,并且会调用onPostExecute()。但是,您可以在此之后获得听众的回调。

所以实际上你并不需要AsyncTask,因为你的uploadTask已经是asychrounous。

答案 1 :(得分:0)

我在使用 AsyncTask 类从firebase获取数据时遇到了这个问题。我注意到onPostExecute方法在从数据库获取数据之前运行。我试图实现一个类来从firebase获取数据,并在收到数据时通过监听器通知我,而不是使用onPostExecute()方法。使用AsyncTask可能是多余的,因为Firebase方法是自异步的,但AysingTask对象在添加进度对话框和类似工作人员的情况下提供了更大的灵活性。如果您有多次从firebase读取的调用,则此类也很有用。你不需要多次编写代码。这是我的班级:

import android.os.AsyncTask;

import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.ValueEventListener;


public class FirebaseDataCenter {

    // this is a class to deal with the database

    private DataFetcher fetcher;

    public FirebaseDataCenter(){
        // empty constructor
    }

    public void readFromDatabase(DatabaseReference databaseReference, OnDataReceived listener){
        fetcher = new DataFetcher();
        fetcher.setDataBaseReference(databaseReference);
        fetcher.onDataRecieved(listener);
        fetcher.execute();
    }



    private class DataFetcher extends AsyncTask<Void, Void, Void> {
        private DatabaseReference dataref;
        private OnDataReceived listener;

        public void setDataBaseReference(DatabaseReference dataref){
            this.dataref = dataref;
        }

        public DatabaseReference getDataRef(){
            return dataref;
        }

        public void onDataRecieved(OnDataReceived listener){
            this.listener = listener;
        }

        public OnDataReceived getListener(){
            return this.listener;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(Void... voids) {
            getData();
            return null;
        }

        public void getData() {
            dataref.addListenerForSingleValueEvent(new ValueEventListener() {

                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    listener.gotData(dataSnapshot.getChildren()); // this listener will hold your Datasnapshot object for further manipulation in your class
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });
        }

        @Override
        protected void onPostExecute(Void voids) {
            super.onPostExecute(voids);
        }
    }
}

interface OnDataReceived {
    void gotData(Iterable<DataSnapshot> data);
    // this is an interface working as a listener when the data is retrieved.
}

要使用该类,您只需要编写以下行:

FirebaseDataCenter fetcher = new FirebaseDataCenter();
        fetcher.readFromDatabase(yourFirebaseReferencePath, new OnDataReceived() {
            @Override
            public void gotData(final Iterable<DataSnapshot> data) {
                  // do whatever you need with the DataSnapshot you recieved from this listener. Notice that this DataSnapshot object is iterable!! 
            }
         });

希望这有帮助,:))