Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Android上同时运行多个异步任务_Android_Ruby On Rails_Android Asynctask - Fatal编程技术网

在Android上同时运行多个异步任务

在Android上同时运行多个异步任务,android,ruby-on-rails,android-asynctask,Android,Ruby On Rails,Android Asynctask,我正在努力允许我的用户在我的Android应用程序中进行调查。调查是在my rails服务器中创建的,调查的选择将发布回rails服务器 到目前为止,对于单选问题来说效果很好——用户的选择被存储并发送到服务器。问题在于多选题——我想我可以循环检查每个复选框,如果选中了该复选框,则通过我用于单选题的AsyncTask将该选项发送到服务器。然而,这似乎只是执行第一次发送的第一个选择 根据其他一些SO帖子,我发现Android似乎在允许异步任务并行运行和不允许异步任务并行运行之间来回切换。有人对如何处

我正在努力允许我的用户在我的Android应用程序中进行调查。调查是在my rails服务器中创建的,调查的选择将发布回rails服务器

到目前为止,对于单选问题来说效果很好——用户的选择被存储并发送到服务器。问题在于多选题——我想我可以循环检查每个复选框,如果选中了该复选框,则通过我用于单选题的AsyncTask将该选项发送到服务器。然而,这似乎只是执行第一次发送的第一个选择

根据其他一些SO帖子,我发现Android似乎在允许异步任务并行运行和不允许异步任务并行运行之间来回切换。有人对如何处理这个问题有建议吗?我想支持回到API 10。提前谢谢

下面是我调用AsyncTask的方式:

private void sendChoice() {
        mQuestionId = mQuestion.getId();
        if (mRadioGroupAnswers != null) {
            mAnswerId = mRadioGroupAnswers.getCheckedRadioButtonId();
            new ChoicePosted().execute();
        }

        if (mAnswerHolder.getChildCount() > 0) {
            for (int i = 0; i < mAnswerHolder.getChildCount(); i++) {
                CheckBox selected = (CheckBox) mAnswerHolder.getChildAt(i);
                if (selected.isChecked()) {
                    mAnswerId = selected.getId();
                    new ChoicePosted().execute();
                }
            }
        }
    }

    private class ChoicePosted extends AsyncTask<Void, Void, Void> {
        protected Void doInBackground(Void... params) {
                Log.i(TAG, "ChoicePosted");

                boolean choicePosted = false;
                try {

                    choicePosted = new SurveyMe().postChoice(
                            "8d707d9fa2b279f381eb416f1be887c0", mQuestionId,
                            mAnswerId);

                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    Log.e(TAG, "Errors: " + e);

                    e.printStackTrace();
                }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            Toast.makeText(getActivity(), "It worked!", Toast.LENGTH_SHORT)
                    .show();
        }
    }
private void sendChoice(){
mQuestionId=mQuestion.getId();
if(mRadioGroupAnswers!=null){
mAnswerId=mRadioGroupAnswers.getCheckedRadioButtonId();
新建ChoicePosted().execute();
}
if(mAnswerHolder.getChildCount()>0){
对于(int i=0;i
传递答案值列表可能是一个更好的选择,而不是依赖
AsyncTask
读取
mAnswerId
变量,该变量可以通过
sendschoices()
方法根据执行顺序进行更改

尝试为您的
ChoicePosted AsyncTask
创建一个构造函数,该构造函数接受一个
List
参数,该参数用于迭代要发送的答案Id,因此迭代将在
AsyncTask
中执行,而不是生成多个
AsyncTasks
(另一个选项可以是通过单个
字符串
发送到
异步任务
。只要
mAnswerId
在所选的异步任务使用时不保持全局和可编辑状态,您就可以了

ChoicePosted
添加构造函数的示例,该构造函数将
列表
中的
字符串
作为答案发送:

private class ChoicePosted extends AsyncTask<Void, Void, Void> {
        List<String> mAnswersToPost;

        public ChoicePosted(List<String> strings){
               mAnswersToPost = strings;
        }

        protected Void doInBackground(Void... params) {
                for (String answer : mAnswersToPost){
                     new SurveyMe().postChoice(
                            "8d707d9fa2b279f381eb416f1be887c0", mQuestionId,
                            answer);
                }
            return null;
        }
    }
因此,您的
AsyncTask
sendschoices()
方法决不会使用相同的
mAnswerId
变量,而是保留自己的副本,这些副本不会被无意中更改

然后,您应该能够从
类中删除
mAnswerId
,当然您需要考虑第一次调用
new ChoicePosted()
(我可以看到您两次调用它)

当然,在这种方法中,
AsyncTask
只运行一次,您可以调整为获取字符串(或使用
AsyncTask
参数。目前您将它们都设置为
Void
,但它们可以用于将参数直接传递到
doInBackground
方法并作为返回类型)

要更深入地了解
AsyncTask
,您可以阅读这篇Android开发者文章。

下面的代码将演示如何在Android中同时运行多个异步任务
包com.vit.test.asynctask;
导入java.util.concurrent.AtomicInteger;
导入android.app.Activity;
导入android.os.AsyncTask;
导入android.os.Bundle;
导入android.os.SystemClock;
导入android.util.Log;
导入android.view.Gravity;
导入android.view.view;
导入android.widget.CheckBox;
导入android.widget.EditText;
导入android.widget.Toast;
/*
*免责声明:此代码是作为快速原型创建的。
*请不要在生产中使用它,因为它既不能处理
*设备配置更改或活动生命周期更改。
*/
公共类MainActivity扩展了活动{
//批处理中要运行的任务数
私有EditText numberOfTasksEditText;
//单个任务的有效负载作业的持续时间
私有EditText singleTaskDurationEditText;
//在两种不同模式之间切换(有/没有并行执行)
私有复选框启用并行执行复选框;
//每个任务一进入其doInBackground()就会增加此计数
//这样就可以跟踪任务执行的顺序
私有原子整数执行任务;
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
numberOfTasksEditText=(EditText)findviewbyd(R.id.tasks\u编号);
singleTaskDurationEditText=(EditText)findViewById(R.id.task\u payload\u duration);
enableParallelExecutionCheckbox=(复选框)findViewById(R.id.enable\u parallel\u execution);
}
单击开始测试时的公共无效(视图v){
if (mAnswerHolder.getChildCount() > 0) {
     List<String> answerList = new ArrayList<String>();
     for (int i = 0; i < mAnswerHolder.getChildCount(); i++) {
         CheckBox selected = (CheckBox) mAnswerHolder.getChildAt(i);
         if (selected.isChecked()) {
             answerList.add(selected.getId());
         }
     }
     new ChoicePosted(answerList).execute();
}
Below code will demonstrtate how to run multiple async task simultaneously in android


package com.vit.test.asynctask;

import java.util.concurrent.atomic.AtomicInteger;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;

/*
 * Disclaimer: this code is created as a quick prototype.
 * Please don't use it in production, because it neither handles 
 * device configuration changes nor the Activity lifecycle changes.
 */
public class MainActivity extends Activity   {

    // the number of tasks to be run in a batch
    private EditText numberOfTasksEditText;

    // the duration of payload job for a single task 
    private EditText singleTaskDurationEditText;

    // switches between 2 different modes (with/without parallel execution)
    private CheckBox enableParallelExecutionCheckbox;

    // each task increments this count as soon as it enters its doInBackground()
    // so this allows to track the order of tasks execution
    private AtomicInteger executedTasksCount;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);       

        numberOfTasksEditText           = (EditText) findViewById(R.id.tasks_number);
        singleTaskDurationEditText      = (EditText) findViewById(R.id.task_payload_duration);
        enableParallelExecutionCheckbox = (CheckBox) findViewById(R.id.enable_parallel_execution);    
        }

    public void onStartTestClicked(View v)      {
        executedTasksCount = new AtomicInteger(0);       // reset this count

        final int numberOfTasks = getIntFromTextView(numberOfTasksEditText);
        final int taskDuration  = getIntFromTextView(singleTaskDurationEditText);

        log("number of tasks to run = " + numberOfTasks);
        log("task payload duration = " + taskDuration + " ms");

        final boolean useParallelExecution = enableParallelExecutionCheckbox.isChecked();        
        log("use parallel execution = " + useParallelExecution);

        Toast toast = Toast.makeText(this, "Please watch the LogCat output", Toast.LENGTH_SHORT);
        toast.setGravity((Gravity.CENTER_HORIZONTAL | Gravity.TOP), toast.getXOffset(), toast.getYOffset());
        toast.show();

        for (int i = 0; i < numberOfTasks; i++)    
        {  
            int taskId = i + 1;
            startTask(taskId, taskDuration, useParallelExecution);
        }
    }

    private void startTask(int taskId, int taskDuration, boolean useParallelExecution)   {      
        TestTask task = new TestTask(taskId, taskDuration);        
        if (useParallelExecution) {
            // this type of executor uses the following params:
            //
            // private static final int CORE_POOL_SIZE = 5;
            // private static final int MAXIMUM_POOL_SIZE = 128;
            // private static final int KEEP_ALIVE = 1;
            //
            // private static final ThreadFactory sThreadFactory = new ThreadFactory() {
            //     private final AtomicInteger mCount = new AtomicInteger(1);
            //
            //     public Thread newThread(Runnable r) {
            //         return new Thread(r, "AsyncTask #" + mCount.getAndIncrement());
            //     }
            // };
            //
            // private static final BlockingQueue<Runnable> sPoolWorkQueue =
            //        new LinkedBlockingQueue<Runnable>(10);

            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

        } else {
            // this is the same as calling task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
            task.execute();
        }
    }

    private int getIntFromTextView(EditText v) {
        int result = 0;
        try {
            result = Integer.parseInt(v.getText().toString());
        } catch (NumberFormatException ignored) {}
        return result;
    }

    private void log(String msg) {
        Log.d("MainActivity", msg);
    }

    private class TestTask extends AsyncTask<Void, Void, Void> /* Params, Progress, Result */ {

        private final int id;
        private final int duration;

        TestTask(int id, int duration) {
            this.id       = id;
            this.duration = duration;
        }

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

            int taskExecutionNumber = executedTasksCount.incrementAndGet();
            log("doInBackground: entered, taskExecutionNumber = " + taskExecutionNumber);
            SystemClock.sleep(duration); // emulates some job
            log("doInBackground: is about to finish, taskExecutionNumber = " + taskExecutionNumber);
            return null;

        }

        private void log(String msg) {
            Log.d("TestTask #" + id, msg);
        }
    }
}
//----place this layout code in xml
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp">

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Number of tasks:" />

        <EditText
            android:id="@+id/tasks_number"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:hint="0"
            android:text="1"
            android:maxLength="4" />

        <View
            android:layout_width="fill_parent"
            android:layout_height="10dp" />

        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Task payload duration (ms):" />

        <EditText
            android:id="@+id/task_payload_duration"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:hint="0"
            android:text="1"
            android:maxLength="5" />

        <View
            android:layout_width="fill_parent"
            android:layout_height="10dp" />

        <CheckBox
            android:id="@+id/enable_parallel_execution"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Execute tasks in parallel" />

        <View
            android:layout_width="fill_parent"
            android:layout_height="10dp" />

        <Button
            android:onClick="onStartTestClicked"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:text="Start Test" />

    </LinearLayout>

</ScrollView>