Skip to content Skip to sidebar Skip to footer

Is It Possible To Pass A Fragment In A Constructor?

I am trying to pass my Fragment to an ASyncTask class so that I can update a widget or two in the fragment once the task completes. Here's what I'm dealing with: public class Login

Solution 1:

As curious says you don't want to be passing Fragments around (they have a 'link' to the activity which is a context and passing contexts is baaad)

You want to pass a small object that can help you call back from your Task to your Fragment.

I would also use an interface. Here's my example:

Fragment:

publicclassLoginFragmentextendsFragmentimplementsOnClickListener, OnLoginListener{

    Button loginButton;
    TextView loginErrorMsg;
    privateProgressDialog progressDialog;

    @OverridepublicvoidonAttach(Activity activity) {
        super.onAttach(activity);

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

    @OverridepublicViewonCreateView(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;

    }

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

    @OverridepublicvoidonLoginSuccess() {
        progressDialog.dismiss();
        // Yayy
    }

    @OverridepublicvoidonLoginFailure() {
        progressDialog.dismiss();
        // Boo
    }
}

The ASyncTask:

publicclassLoginTaskextendsAsyncTask<String, Void, Integer> {

    privatefinal OnLoginListener listener;

    publicinterfaceOnLoginListener{
        publicvoidonLoginSuccess();
        publicvoidonLoginFailure();
    }

    publicLoginTask(OnLoginListener listener) {
        this.listener = listener;
    }

    @Overrideprotected Integer doInBackground(String... params) {
        try{
            // Something
        } catch (SomeException e){
            listener.onLoginFailure();
        }
        returnnull;
    }

    @OverrideprotectedvoidonPostExecute(Integer result) {
        super.onPostExecute(result);
        listener.onLoginSuccess();
    }

}

If you get your head around interfaces your world will open up and your code will look less like the amazon jungle and more like a well organised garden ;-)

Solution 2:

I suggest you use a Callback interface for this purpose. It is generally not a good idea to pass in UI-specific (actually, context-specific) objects to an AsyncTask.

Here's what I suggest. With this approach, you don't even need to pass in your Fragment around.

Disclaimer: I have not actually tried running this code - just typed it off the top of my head. So it may not even compile - it is just intended to be a guide.

interfaceLoginCallback{
    voidonLoginSuccess();
    voidonLoginFailure();
}


//onCreate codeTextViewloginErrorMsg= (EditText)activity.findViewById(R.id.loginErrorMsg);
EditTextuserName= (EditText)activity.findViewById(R.id.emailEditText);
EditTextpasswordEdit= (EditText)activity.findViewById(R.id.passEditText);


LoginTaskloginTask=newLoginTask(newLoginCallback(){
    @OverrideprotectedvoidonLoginSuccess(){
        //Update UI
    }

        @OverrideprotectedvoidonLoginFailure(){
        //Update UI
    }
});

loginTask.execute();



//LoginTask code.publicclassLoginTaskextendsAsyncTask<String, Void, Integer> {
    LoginCallback callback;
    ProgressDialog progressDialog;

    publicLoginTask(LoginCallback callback){
        this.callback = callback;


        @OverrideprotectedvoidonPreExecute(){
            progressDialog = newProgressDialog(getActivity());
            progressDialog.setMessage("Logging in...");

        }

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

        }

        @OverrideprotectedvoidonPostExecute(Integer result) {
           progressDialog.dismiss();
           if(loginSuccess){
                callback.onLoginSuccess();
           } else {
                callback.onLoginFailure();
           }
        }
    }
}

Post a Comment for "Is It Possible To Pass A Fragment In A Constructor?"