0

I am learning Android and came across very strange behavior. I am using Retrofit2 as REST library in android (using asynchronous calls). I want to send authCode and TokenId as Google advise it on my server. When I check if user has set password I do a response. If I return code 206 means that user has not yet set password on my back-end server. So I want to start a fragment that user will enter password (I am also say that I defined LoginFragment and RegistrationFragment that both work on this Activity). But here is the trick, Fragment get called and when my onCreateView is executed there but TextView and Button has null value why is that? I assume that there is a problem since this is run on background thread but I may be mistaken. Is there a better way to achieve what I want?

  • My Retrofit call:

    private void sendTokenToServer(String idToken, String authCode, String email){
        Log.d("APP", authCode);
        GoogleTokenRequest googleTokenRequest = new GoogleTokenRequest();
        googleTokenRequest.setTokenId(idToken);
        googleTokenRequest.setAuthCode(authCode);
        googleTokenRequest.setEmail(email);
        ApiInterface apiService =
            ApiClient.getClient().create(ApiInterface.class);
    
    
    
        Call<GoogleTokenRequest> call = apiService.sendTokenToBackend(googleTokenRequest);
        Log.d("APP", call.toString());
    
        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
    
    
        call.enqueue(new Callback<GoogleTokenRequest>() {
        //execute za sinhroni klic, enqueue za asinhroni
        @Override
        public void onResponse(Call<GoogleTokenRequest> call, Response<GoogleTokenRequest> response) {
                String access_token = response.headers().get("Authorization");
                Log.d("APP", access_token);
                 prefs.edit().putString("access_token",access_token).commit();
                int statusCode = response.code();
    
                if (statusCode == 206) {
                    SetPasswordFragment registerFragment = new SetPasswordFragment();
                    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
                    fragmentTransaction.replace(R.id.fragment_login_container, registerFragment);
                    fragmentTransaction.commit();
                }
                else{
                    Intent intent = new Intent(getApplicationContext(), MainActivity.class);
                    startActivity(intent);
    
                   }
    
  • This is my fragment code:

    public class SetPasswordFragment extends Fragment {

    private OnSetPasswordListener onSetPasswordListener;
    public SetPasswordFragment() {
        // Required empty public constructor
    }
    
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnSetPasswordListener) {
            onSetPasswordListener = (OnSetPasswordListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        super.onCreate(savedInstanceState);
        LayoutInflater lf = getActivity().getLayoutInflater();
    
        View rootView =  lf.inflate(R.layout.fragment_set_password, container, false);
        Button setPasswordButton = (Button) rootView.findViewById(R.id.btn_set_password_ok);
        TextView textView = (TextView) rootView.findViewById(R.id.set_password_message);
    
        Log.d("APP",rootView.toString());
    
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
        String username = prefs.getString("username", "User");
    
        textView.setText(String.format(getString(R.string.set_password_message), username));
    
        setPasswordButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                setPasswordValidate();
            }
        });
    
        return rootView;
    }
    
  • this is the logcat: enter image description here

Janki Gadhiya
  • 4,492
  • 2
  • 29
  • 59
alphiii
  • 1,597
  • 3
  • 21
  • 27
  • 1
    You could only inflate and return the view in the onCreateView and do all other Button and TextView stuff in the onViewCreated method of the fragment – Narayan Acharya Jul 31 '16 at 13:02
  • Never thought about it, will try, lets hope it works. – alphiii Jul 31 '16 at 13:04
  • Possible duplicate of [What is a NullPointerException, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – Janki Gadhiya Jul 31 '16 at 13:57

2 Answers2

1

This should probably fix it :

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    super.onCreate(savedInstanceState);

    View rootView =  inflater.inflate(R.layout.fragment_set_password, container, false);
    return rootView;
}

@Override
public void onViewCreated(View view){
Button setPasswordButton = (Button) view.findViewById(R.id.btn_set_password_ok);
    TextView textView = (TextView) view.findViewById(R.id.set_password_message);


    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
    String username = prefs.getString("username", "User");

    textView.setText(String.format(getString(R.string.set_password_message), username));

    setPasswordButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            setPasswordValidate();
        }
    });

}

Note : I dont rexactly remember the exact parameters for the onViewCreated method but view is definitely there. So I guess this should work.

Narayan Acharya
  • 1,459
  • 1
  • 18
  • 33
  • Sadly this does not work, it is the same as it was in onCreateView. If I remove setText and setOnclickListener it works. But that is not what I want. The reference (R.id....) is set correctly. – alphiii Jul 31 '16 at 13:21
  • Can you share the logcat what actually happens. – Narayan Acharya Jul 31 '16 at 13:34
  • It says null object reference on textView.setText(String.format(getString(R.string.set_password_message), username)); – alphiii Jul 31 '16 at 13:44
  • In that case please verify that the inflated view contains the ids of the button and textview. I don't see any other reason why they should be null. – Narayan Acharya Jul 31 '16 at 13:49
0

I know my problem description does not point to the real problem that I found but still I will post it since maybe it will help someone. I my case it was problem in xml file I just removed android:fillViewport="true" or set it to false and it works.

alphiii
  • 1,597
  • 3
  • 21
  • 27