Можно ли передать фрагмент в конструкторе? - PullRequest
0 голосов
/ 30 марта 2012

Я пытаюсь передать свой фрагмент классу ASyncTask, чтобы я мог обновить один или два виджета во фрагменте после завершения задачи.Вот что я имею в виду:

public class LoginFragment extends Fragment {

    Button loginButton;
    TextView loginErrorMsg;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.loginfragment, container, false);
    }

    public OnClickListener loginListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.v("LoginF", "onclick");
            ProgressDialog progressDialog = new ProgressDialog(getActivity());
            progressDialog.setMessage("Logging in...");
            LoginTask loginTask = new LoginTask((Polling) getActivity(), progressDialog);
            loginTask.execute();
        }
    };

И LoginTask:

public class LoginTask extends AsyncTask<String, Void, Integer> {

private ProgressDialog progressDialog;
private Polling activity;
private int id = -1;
private JSONParser jsonParser;
private static String loginURL = "http://davidjkelley.net/android_api/";
private static String registerURL = "http://davidjkelley.net/android_api/";
private static String KEY_SUCCESS = "success";
private static String KEY_ERROR = "error";
private static String KEY_ERROR_MSG = "error_msg";
private static String KEY_UID = "uid";
private static String KEY_NAME = "name";
private static String KEY_EMAIL = "email";
private static String KEY_CREATED_AT = "created_at";
TextView loginErrorMsg = (EditText)activity.findViewById(R.id.loginErrorMsg);
EditText userName = (EditText)activity.findViewById(R.id.emailEditText);
EditText passwordEdit = (EditText)activity.findViewById(R.id.passEditText);

public LoginTask(Polling activity, ProgressDialog progressDialog)
{
    this.activity = activity;
    this.progressDialog = progressDialog;
}

Поэтому я хотел бы добавить третий параметр в конструктор LoginTask, по сути, экземпляр моегоLoginFragment.Моя цель состоит в том, чтобы обновить либо TextView, либо поставить Toast на экране, чтобы уточнить, будет ли вход успешным или неудачным: как сейчас, у пользователя нет возможности рассказать, как проходил вход в систему.Идеи?

Ответы [ 2 ]

4 голосов
/ 30 марта 2012

Как любопытно говорит, что вы не хотите передавать фрагменты (у них есть «ссылка» на действие, которое является контекстом, а передача контекста - baaad)

Вы хотите передать небольшой объект, который может помочь вам перезвонить из вашей Задачи в ваш Фрагмент.

Я бы тоже использовал интерфейс. Вот мой пример:

Фрагмент:

public class LoginFragment extends Fragment implements OnClickListener, OnLoginListener{

    Button loginButton;
    TextView loginErrorMsg;
    private ProgressDialog progressDialog;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        progressDialog = new ProgressDialog(activity);
        progressDialog.setMessage("Logging in...");
    }

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

        loginButton = v.findViewById(R.id.button);
        loginButton.setOnClickListener(this);

        return v;

    }

    @Override
    public void onClick(View v) {
        switch(v.getId()){
        case R.id.button:
            Log.v("LoginF", "onclick");
            progressDialog.show();
            LoginTask loginTask = new LoginTask(this);
            loginTask.execute();
            break;
        default:
            break;
        }
    }

    @Override
    public void onLoginSuccess() {
        progressDialog.dismiss();
        // Yayy
    }

    @Override
    public void onLoginFailure() {
        progressDialog.dismiss();
        // Boo
    }
}

ASyncTask:

public class LoginTask extends AsyncTask<String, Void, Integer> {

    private final OnLoginListener listener;

    public interface OnLoginListener{
        public void onLoginSuccess();
        public void onLoginFailure();
    }

    public LoginTask(OnLoginListener listener) {
        this.listener = listener;
    }

    @Override
    protected Integer doInBackground(String... params) {
        try{
            // Something
        } catch (SomeException e){
            listener.onLoginFailure();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Integer result) {
        super.onPostExecute(result);
        listener.onLoginSuccess();
    }

}

Если вы разберетесь с интерфейсами, ваш мир откроется, и ваш код будет выглядеть не так, как джунгли амазонки, а скорее как хорошо организованный сад; -)

1 голос
/ 30 марта 2012

Я предлагаю вам использовать интерфейс Callback для этой цели. Как правило, не рекомендуется передавать специфичные для пользовательского интерфейса (на самом деле контекстные) объекты в AsyncTask.

Вот что я предлагаю. При таком подходе вам даже не нужно передавать Fragment вокруг.

Отказ от ответственности: я на самом деле не пробовал запускать этот код - просто набрал его у меня на голове. Так что он может даже не скомпилироваться - он просто предназначен для руководства.

interface LoginCallback{
    void onLoginSuccess();
    void onLoginFailure();
}


//onCreate code
TextView loginErrorMsg = (EditText)activity.findViewById(R.id.loginErrorMsg);
EditText userName = (EditText)activity.findViewById(R.id.emailEditText);
EditText passwordEdit = (EditText)activity.findViewById(R.id.passEditText);


LoginTask loginTask = new LoginTask(new LoginCallback(){
    @Override
    protected void onLoginSuccess(){
        //Update UI
    }

        @Override
    protected void onLoginFailure(){
        //Update UI
    }
});

loginTask.execute();



//LoginTask code.
public class LoginTask extends AsyncTask<String, Void, Integer> {
    LoginCallback callback;
    ProgressDialog progressDialog;

    public LoginTask(LoginCallback callback){
        this.callback = callback;


        @Override protected void onPreExecute(){
            progressDialog = new ProgressDialog(getActivity());
            progressDialog.setMessage("Logging in...");

        }

        @Override
        protected Integer doInBackground(String... params){
           //Do you login logic here.

        }

        @Override
        protected void onPostExecute(Integer result) {
           progressDialog.dismiss();
           if(loginSuccess){
                callback.onLoginSuccess();
           } else {
                callback.onLoginFailure();
           }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...