在Android中,我如何一次运行一个AsyncTask?

时间:2014-01-13 22:53:32

标签: android android-asynctask

我有一个由一组方法调用的AsyncTask:

makeCall1();
makeCall2();
makeCall3();
makeCall4();
makeCall5();

每个问题都有一个“状态信息”,需要在运行时显示。因为我让它们像我一样运行,所以它们一起运行,“状态信息”做了一个大的改变。我想要的是让它逐步完成每个调用,只在第一个AsyncTask完成后才生成下一个调用。

我的异步完成如下:

public class JSONParser extends AsyncTask<String, String, JSONObject> {

        InputStream is = null;
        JSONObject json = null;
        String outPut = "";
        protected void onPreExecute(String f){

        }

        @Override
        protected JSONObject doInBackground(String... params) {
            // TODO Auto-generated method stub
            ...
            publishProgress(params[3]);
            ...

            return json;
        }

        protected void onProgressUpdate(String...values) {
            statusMessage.setText(values[0]);
         }

        protected void onPostExecute(JSONObject result) {

        }
    }

一次拨打一个电话的最佳方法是什么?

-----编辑-----

要求的附加代码

我已经更改了下面的内容的名称并放置了“....”,其中代码片段在保存到数据库时并不真正相关:

public class SplashScreen extends Activity {

     protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);

        statusMessage = (TextView) findViewById(R.id.statusMessage);
    }

    protected void onResume(){
        super.onStart();
        if(isNetworkAvailable()){
            statusMessage.setText("Connection Found");
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    final String appUpdateDate = null;
                    getAPI1(appUpdateDate);
                    getAPI2(appUpdateDate);
                    getAPI3(appUpdateDate);
                    getAPI4(appUpdateDate);
                    getAPI5(appUpdateDate);
                    getAPI6(appUpdateDate);

                    endSplash();
                }

            }, SPLASH_TIME_OUT);
        }
        else {
            statusMessage.setText("No Connection Found");
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    endSplash();
                }

            }, SPLASH_TIME_OUT);
        }

    }

    public void endSplash(){

        ....
        goes to main activity after timeout
        ....

    }

     private boolean isNetworkAvailable() {
        ....
        checks for internet connection
        ....
    }

    //this is an example of getAPI1. There are 5 more but each do a different database and api call. The AsyncTask is what does the api call and parses the json it returns.
    public void getAPI1(String appUpdateDate){
        String URL = "http://API_URL";
        String requestType = "X";
        String getType = "Y";
        URL = URL+requestType+"/"+getType;
        SQLiteDatabase database = APIDB.getWritableDatabase();
        try {
            JSONObject output = new JSONParser().execute(new String[] {URL,consumerKey,sharedSecret,"Updating X"}).get();
            JSONArray jsonx = output.getJSONArray("Data");

            ....
                        runs through jsonX and saves data to database
                        ....


        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    public class JSONParser extends AsyncTask<String, String, JSONObject> {

        InputStream is = null;
        JSONObject json = null;
        String outPut = "";
        protected void onPreExecute(String f){

        }

        @Override
        protected JSONObject doInBackground(String... params) {
            // TODO Auto-generated method stub
            publishProgress(params[3]);
            String url = params[0];
            String ck = params[1];
            String ss = params[2];
            Log.d("url",url);
            Log.d("ck",ck);
            Log.d("ck",ss);
            List<NameValuePair> values = new ArrayList<NameValuePair>();
            values.add(new BasicNameValuePair("ConsumerKey", ck));
            values.add(new BasicNameValuePair("SharedSecret", ss));
            try {

                ....
                        get the json from the api
                        ....

            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

            ....
                parse the json to be returned
                ....

            } catch (Exception e) {
                Log.e("Buffer Error", "Error converting result " + e.toString());
            }
            try {
                json = new JSONObject(outPut);
            } catch (JSONException e) {
                Log.e("JSON Parser", "Error parsing data " + e.toString());
            }
            // return JSON String

            return json;
        }

        protected void onProgressUpdate(String...values) {
            statusMessage.setText(values[0]);
         }

        protected void onPostExecute(JSONObject result) {
        }
    }

}

3 个答案:

答案 0 :(得分:2)

从API级别11 / Honeycomb开始,默认的asynctask执行程序为SERIAL_EXECUTOR,因此单个asynctasks已经串行执行,除非您明确指定例如THREAD_POOL_EXECUTOR。因此,如果您的最小和目标SDK版本都是11或更高,只需execute()您的asynctasks,它们将在执行程序可用时立即运行。

要处理状态消息等UI更新,请使用onPreExecute()onProgressUpdate()和/或onPostExecute()。如果需要将其他参数传递给异步任务,可以在构造函数args中赋予它们并存储在成员变量中。

答案 1 :(得分:1)

public class JSONParser extends AsyncTask<String, String, JSONObject> {
OnFinished onFinished;

JsonParser(OnFinished onFinishedWithTask) {
    this.onFinished = onFinishedWithTask;
}

InputStream is = null;
JSONObject json = null;
String outPut = "";

protected void onPreExecute(String f) {

}

@Override
    protected JSONObject doInBackground(String... params) {
        // TODO Auto-generated method stub
        ...
        publishProgress(params[3]);
        ...

        return json;
    }

protected void onProgressUpdate(String... values) {
    statusMessage.setText(values[0]);
}

protected void onPostExecute(JSONObject result) {
    this.onFinished.onFinishedWithTask();

}

}

public interface OnFinished {
    public void onFinishedWithTask();
}

这样的事可能适合你。

然后调用第一个,当它完成后调用第二个,依此类推......如果你需要在'onprogressupdate'中更新ui,只需在界面中创建另一个方法并调用它。

下面是一个更大的例子,让您了解一个人如何做到这一点:

public class DownloadWebPage extends AsyncTask<String, Integer, StringBuilder> {
    private OnProgressUpdate updateInter;
    private String url;

    public DownloadWebPage() {
        super();
    }

    public DownloadWebPage(OnProgressUpdate updateInter) {
        this.updateInter = updateInter;
    }

    public DownloadWebPage(OnProgressUpdate updateInter, String url) {
        this(updateInter);
        this.url = url;
    }

    @Override
    protected StringBuilder doInBackground(String... url) {
        System.out.println("start downloading");
        try {
            System.out.println("url 0 =" + url[0]);
            HttpClient client = new DefaultHttpClient();
            HttpGet request = new HttpGet(url[0]);
            HttpResponse response = client.execute(request);
            BufferedReader rd = new BufferedReader(new InputStreamReader(
                    response.getEntity().getContent()));
            long content = response.getEntity().getContentLength();
            String line = "";
            StringBuilder htmlBuilder = new StringBuilder();
            long bytesRead = 0;
            while ((line = rd.readLine()) != null) {
                htmlBuilder.append(line);
                bytesRead = bytesRead + line.getBytes().length + 2;
                publishProgress(new Integer[] { (int) (((double) bytesRead / (double) content) * 100) });
            }
            System.out.println("end downloading");
            return htmlBuilder;
        } catch (IOException e) {
            System.out.println(e.toString());
            return null;
        }

    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        if (values[0].equals(Math.abs(values[0]))) {
            updateInter.onUpdate(values[0]);
        } else if (!values[0].equals(Math.abs(values[0]))) {
            updateInter.onUpdateFailure();
        }
    }

    @Override
    protected void onPostExecute(StringBuilder result) {
        if (result == null) {
            updateInter.onFailure();
        } else if (result != null) {
            updateInter.onSuccess(result);
        }

    }

    public void setOnProgressUpdate(OnProgressUpdate updateInter) {
        this.updateInter = updateInter;

    }

    public void downloadHtml() {
        if (url == null) {
            updateInter.onFailure();
            return;
        }
        System.out.println("STATUS=" + getStatus());
        if (getStatus().equals(AsyncTask.Status.FINISHED)) {
            DownloadWebPage iseDownloader = new DownloadWebPage();
            iseDownloader.setOnProgressUpdate(updateInter);
            iseDownloader.execute(new String[] { url });
        } else if (getStatus().equals(AsyncTask.Status.RUNNING)) {
        } else {
            execute(new String[] { url });
        }
    }

    public void downloadHtml(String urlToDownload) {
        this.url = urlToDownload;
        downloadHtml();
    }
}

继承人界面:

   public interface OnProgressUpdate {
    public void onUpdate(Integer percentProgress);

    public void onUpdateFailure();

    public void onSuccess(StringBuilder result);

    public void onFailure();

}

Heres用法:

public final class OnProgressUpdater implements OnProgressUpdate {
        private final FortschoolsFragment fortSchoolsFragment;
        private final SchoolActivity a;

        public OnProgressUpdater(SherlockFragment fragment, Activity a) {
            this.fortSchoolsFragment = (FortschoolsFragment) fragment;
            this.a = (SchoolActivity) a;
            this.a.startRefreshing();
            this.a.disableSpinner();
        }

        @Override
        public void onUpdate(Integer percentProgress) {
            // TODO Auto-generated method stub

        }

        @Override
        public void onUpdateFailure() {
            // TODO Auto-generated method stub

        }

        @Override
        public void onSuccess(StringBuilder result) {
            final Document doc = Jsoup.parse(result.toString());
            final Site site = new FortSchoolSite(doc);
            dataList = site.getNews();
            if (JavaUtility.isNull(fortSchoolsFragment.getSherlockActivity())) {
                return;
            }
            mListViewAdapter = new DataAdapter(fortSchoolsFragment
                    .getSherlockActivity().getApplicationContext(), dataList);
            mListView.setAdapter(mListViewAdapter);
            this.a.stopRefreshing();
            this.a.enableSpinner();

        }

        @Override
        public void onFailure() {
            this.a.stopRefreshing();
            this.a.enableSpinner();
            Toast.makeText(a.getApplicationContext(), "Something Went Wrong",
                    Toast.LENGTH_LONG).show();

        }

    }

现在使用以下方法调用OnProgressUpdater:

DownloadWebPage page = new DownloadWebPage(new OnProgressUpdater(this,
                getSherlockActivity()), this.mSchool.getSchoolUrl());

page.downloadHtml();

我们正在制作自己的 OnClickListener

回到你的例子。当调用接口的onFinishedWithTask();方法时,我们只会启动另一个asynchtask。

另一种选择是跳过* AsynchTask * 并使用传统的java线程。你将创建一个实现Runnable的私有内部类,然后在run()中完成你的工作;方法并通过runOnUiThread方法更新ui。

跳过asynchtask的示例:

protected class SdfaOverviewThread implements Runnable {
        private static final String SOMEURL = "SOMEURLGOESHERE";

        @Override
        public void run() {
                   //not proper but does illustrate point
            Document doc = Jsoup.connect(SOMEURL).get();
            final Document runOnUiDoc = doc;
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
/* Html parsing is just an example showing what one could do.
 * Do not worry about fragment details either they are just illustrating a point*/ 
                    SdfaOverviewFragment sdfaOverviewFrag = ((SdfaOverviewFragment) getSupportFragmentManager()
                            .findFragmentById(R.id.FrameLayout1));
                    String theme = runOnUiDoc.select("head").select("style")
                            .get(1).toString();
                    String upcomingEvents = runOnUiDoc.select(
                            "div#sw-innerWrap2").toString();
                    String news = runOnUiDoc.select("div#sw-newsContainer")
                            .toString();
                    String quickLinks = runOnUiDoc.select("div.sw-column")
                            .toString();
                    String html = theme + upcomingEvents; //+ news + quickLinks;
                    sdfaOverviewFrag.getWebView().loadDataWithBaseURL(
                            SOMEURL, html, "text/html", "UTF-8",
                            SOMEURL);

                }
            });
            Log.d(TAG, "Finished Running Thread");
        }
    }

现在我们执行:

Thread thread = new Thread(new SdfaOverviewThread());
    thread.start();

跳过Asynchtask也可以适用于你的情况。

回顾一下,你可以:

  1. 使用asynchtask中的接口并拥有要使用这些方法的类:创建实现接口的匿名类或私有内部类。
  2. 跳过asynchtask并使用传统的java线程。
  3. 使用您认为创建最易维护代码的方法。

    修改 我只能给你一些例子;考虑发布更多代码。

    public class JSONParser extends AsyncTask<String, String, JSONObject> {
        private OnFinished onFinished;
    
        public JSONParser(OnFinished onFinished) {
            this.onFinished = onFinished;
        }
    
        @Override
        protected JSONObject doInBackground(String... arg0) {
            JSONObject object = new JSONObject();
            // get data from arg0
            return object;
        }
    
        @Override
        protected void onProgressUpdate(String... values) {
            onFinished.onProgressUpdate(Integer.parseInt(values[0]));
        }
    
        @Override
        protected void onPostExecute(JSONObject result) {
            onFinished.onFinishedWithTask(result);
        }
    }
    
    public interface OnFinished {
        public void onProgressUpdate(Integer percentProgress);
    
        public void onFinishedWithTask(JSONObject object);
    }
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Stack<String> data = new Stack<String>();
            data.push("jsonData");
            data.push("jsonData");
            data.push("jsonData");
            data.push("jsonData");
            data.push("jsonData");
            JSONParser parser = new JSONParser(new Parser(data));
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        private class Parser implements OnFinished {
            private Stack<String> stack;
    
            public Parser(Stack<String> stack) {
                this.stack = stack;
            }
    
            @Override
            public void onProgressUpdate(Integer percentProgress) {
                // update ui from percent progress;
    
            }
    
            @Override
            public void onFinishedWithTask(JSONObject object) {
    
                // if their are no more objects left we will do nothing or else we
                // will create a new Asynchtask
                if (stack.isEmpty()) {
                    return;
                }
                new JSONParser(this).execute(stack.pop());
    
            }
    
        }
    
    }
    

    基本思想是,当调用onFinishedTask(JsonObject obj)时,你将从JsonObject obj更新用户界面,然后启动一个新的asynchtask,直到你的数据用完为止。

    做类似的事情(你只实例化一次):

       public class JSONParser extends AsyncTask<String, String, JSONObject> {
    
            InputStream is = null;
            JSONObject json = null;
            String outPut = "";
            private int api;
            public JSONParser(int api) {
            this.api= api;
            }
    
            protected void onPreExecute(String f){
    
            }
    
            @Override
            protected JSONObject doInBackground(String... params) {
                String appUpdateDate = params[0];
                String url = null;
                String ck = null;
                String ss = null;
                String updating = null;
                switch(api){
                case
                11:
                    String URL = "http://API_URL";
                String requestType = "X";
                String getType = "Y";
                URL = URL+requestType+"/"+getType;
                SQLiteDatabase database = APIDB.getWritableDatabase();
                /*
                 * Write to vars url ck ss updating
                 */
    
                    break;
                }
    
    
    
    
                Log.d("url",url);
                Log.d("ck",ck);
                Log.d("ck",ss);
                List<NameValuePair> values = new ArrayList<NameValuePair>();
                values.add(new BasicNameValuePair("ConsumerKey", ck));
                values.add(new BasicNameValuePair("SharedSecret", ss));
                try {
    
                    ....
                            get the json from the api
                            ....
    
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                } catch (ClientProtocolException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
                ....
                    parse the json to be returned
                    ....
    
                } catch (Exception e) {
                    Log.e("Buffer Error", "Error converting result " + e.toString());
                }
                try {
                    json = new JSONObject(outPut);
                } catch (JSONException e) {
                    Log.e("JSON Parser", "Error parsing data " + e.toString());
                }
                // return JSON String
    
                return json;
            }
    
            protected void onProgressUpdate(String...values) {
                statusMessage.setText(values[0]);
             }
    
            protected void onPostExecute(JSONObject result) {
                /*
                 * Do something to update ui with result
                 */
                api++;
                if(api >  6){
                    return;
                }
                new JSONParser(api).execute("insert data here");
        }
    

答案 2 :(得分:0)

因为这些方法不接受任何变量,为什么不只是在每个函数中都有一个回调函数,并且对下一个函数进行超时并捎带它们?