【问题标题】:Asynctask for downloading data and saving into variable?用于下载数据并保存到变量中的异步任务?
【发布时间】:2016-03-19 14:59:31
【问题描述】:

我已经使用 Retriever.getCourses(username,password) 完成了下载部分,但是下面的代码在稍后将 Values.Courses 设置为 null 时给了我一个错误。我想我写错了 AsyncTask。谢谢!

public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {

    private final String muser;
    private final String mPassword;
    private boolean checked;
    private ArrayList<Course> crs;
    private String name;
    private ArrayList<Teacher> tc;

    UserLoginTask(String user, String password) {
        muser = user;
        mPassword = password;

    }

    @Override
    protected Boolean doInBackground(Void... params) {
        // TODO: attempt authentication against a network service.

        try {

                return Retriever.logInTest(muser, mPassword);


        } catch (Exception e) {
            return false;
        }

        // TODO: register the new account here.
    }



    @Override
    protected void onPostExecute(final Boolean success) {
        mAuthTask = null;
        showProgress(false);

        if (success) {
            SharedPreferences sharedPref = Login.this.getSharedPreferences("Login",Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = sharedPref.edit();
            editor.putString("Username", muser);
            editor.putString("Password", mPassword);

            crs = Retriever.getCourses(muser, mPassword);

            Values.courses = crs;
            editor.commit();

            Intent intent = new Intent(Login.this,MainActivity.class);
            startActivity(intent);
            finish();
        } else {
            mPasswordView.setError(getString(R.string.error_incorrect_password));
            mPasswordView.requestFocus();
        }

    }
    @Override
    protected void onCancelled() {
        mAuthTask = null;
        showProgress(false);
    }

}

public class UserCourseTask extends AsyncTask<Void, Void, ArrayList>{

    private String username;
    private String password;
    private ArrayList<Course> courses;

    public UserCourseTask(String user, String pass)
    {
        username = user;
        password = pass;
    }


    protected ArrayList doInBackground(Void... params)
    {
        try{
            courses = Retriever.getCourses(username,password);
            return courses;
        }
        catch (Exception e){
            Log.e("MYAPP", "exception", e);
        }
        return courses;
    }

    protected void onPostExecute(ArrayList<Course> result)
    {
        setCourses(result);
    }
}

在成绩片段中。 courses.size() 导致错误

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootview = inflater.inflate(R.layout.fragment_grades, container, false);
    ListView yourListView = (ListView) rootview.findViewById(R.id.listview);
    ArrayList<Course> courses = Values.courses;
    for(int i = 0; i<courses.size();i++)
    {
        if(courses.get(i).getSubject().equals("Lunch"))
        {
            courses.remove(i);
            break;
        }
    }
    yourListView.setAdapter(new CourseAdapter(rootview.getContext(),courses));
    yourListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

            Values.assignments = Values.courses.get(position).getAssignments();
            Values.assingmentsclass = Values.courses.get(position).getSubject();
            Intent intent = new Intent(getActivity(), Scrnassign.class);
            startActivity(intent);

        }
    });


    return rootview;

}

【问题讨论】:

  • 我假设Values.courses 是一些静态变量?您不应该使用静态变量在 Android 中的类之间传递数据
  • 另外,这不应该编译,因为您的 AsyncTask 未定义为返回 ArrayList&lt;Course&gt;
  • 我应该使用什么来代替静态变量?
  • 通过接口异步回调你的Activity。 stackoverflow.com/a/35210468/2308683
  • 它仍然说Values.courses 为空,因为 AsyncTask 没有执行并立即得到结果。因此类的异步部分......你必须等到 doInBackground 和 onPostExecute 结束才能使用你的变量。

标签: java android android-asynctask


【解决方案1】:

在 doInBackground 中,您返回了 null,而是返回了课程。您返回的内容将作为参数发送到 onPostExecute

【讨论】:

  • 我猜这是因为 AsyncTask 配置为 Void、Void、Void。当方法的返回类型为 Void 时,除了 null 之外,可能没有什么可以返回的了。
  • @Jägermeister 是正确的。您应该更改以下两件事:也扩展 AsyncTask,返回课程;
  • @Jägermeister 那么onPostExecute的参数怎么会有参数的Arraylist呢?
  • 谢谢,但我将代码更改为那个,它仍然说 Values.courses 为空?我更新了原来的问题
【解决方案2】:

正如 cmets 中提到的并提到 my other answer,AsyncTask 是异步的,因此得名。换句话说,您不能保证您在onPostExecute 中分配的变量的值,并且您不应该在您的活动/片段中使用这些变量,直到您确定它们具有值。

适当处理异步性质并确保您有值的方法是使用回调函数。从那个链接,我定义了一个通用接口来在类之间传递结果。

public interface AsyncResponse<T> {
    void onResponse(T response);
}

你可以定义你的 AsyncTasks 来登录

public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {

    private final String muser;
    private final String mPassword;
    private final AsyncResponse<Boolean> callback;

    public UserLoginTask(String user, String password, AsyncResponse<Boolean> callback) {
        this.muser = user;
        this.mPassword = password;
        this.callback = callback;
    }

    @Override
    protected Boolean doInBackground(Void... voids) {

        boolean login = false;

        // TODO: Some network operation
        try {
            login = doLogin(this.muser, this.mPassword);
        } catch (Exception e) {
            Log.e("LoginError", e.getMessage());
        }

        return login;
    }

    @Override
    protected void onPostExecute(Boolean response) {
        if (callback != null) {
            callback.onResponse(response);
        }
    }
}

并获得课程

public class GetCoursesTask extends AsyncTask<Void, Void, List<Course>> {

    private final String username;
    private final String password;
    private final AsyncResponse<List<Course>> callback;

    public GetCoursesTask(String username, String password, AsyncResponse<List<Course>> callback) {
        this.username = username;
        this.password = password;
        this.callback = callback;
    }

    @Override
    protected List<Course> doInBackground(Void... voids) {
        List<Course> courses = new ArrayList<Course>();

        // TODO: Some network operation
        try {
            courses.addAll(getCourses(username, password));
        } catch (Exception e) {
            Log.e("GetCoursesError", e.getMessage());
        }

        return courses;
    }

    @Override
    protected void onPostExecute(List<Course> response) {
        if (callback != null) {
            callback.onResponse(response);
        }
    }
}

注意简单的onPostExecute 只是将响应转发到构造函数中定义的接口。

现在,在您的登录活动中,您可以使用这样的代码

UserLoginTask loginTask = new UserLoginTask(
        "username",
        mPasswordView.getText().toString(),
        new AsyncResponse<Boolean>() {
            @Override
            public void onResponse(Boolean response) {
                if (response) {
                    // TODO: Save data in SharedPreference
                    Intent loginIntent = new Intent(LoginActivity.this, CoursesActivity.class);
                    loginIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(loginIntent);
                    finish();
                } else {
                    mPasswordView.setError("Incorrect Password");
                    mPasswordView.requestFocus();
                }
            }
        }
);
loginTask.execute();

在课程片段中

private CourseAdapter adapter;
private ListView yourListView;
private ProgressDialog progress;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_grades, container, false);

    this.yourListView = (ListView) v.findViewById(R.id.listview);
    this.adapter = new CourseAdapter(getContext(), new ArrayList<Course>());
    this.yourListView.setAdapter(adapter);

    this.progress = new ProgressDialog(getContext());
    this.progress.setMessage("Loading Courses...");

    fetchCourses();

    return v;
}

private void fetchCourses() {
    this.progress.show();

    GetCoursesTask getCoursesTask = new GetCoursesTask(
            "username",
            "password",
            new AsyncResponse<List<Course>>() {
                @Override
                public void onResponse(List<Course> response) {
                    adapter.clear();
                    adapter.addAll(response);
                    adapter.notifyDataSetChanged();

                    progress.hide();
                }
            });
    getCoursesTask.execute();
}

【讨论】:

    猜你喜欢
    • 2015-04-08
    • 2021-09-04
    • 2020-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    相关资源
    最近更新 更多