0

I created a ListDialog extending a DialogFragment class and I have a problem with understanding of this code in the DijalogX class

((MainActivity)getActivity()).setTextField(selectedItem);

I understand that with this code above I put selected String variable to the setTextField method as an argument and after that this variable is showed in TextView on MainActivity class.

My questions:

  • Why I need a cast from getActivity() to the MainActivity and how I get access from DijalogX(fragment) to the method setTextField in MainActivity? Please explain a little about this process.
  • I also tried instead of ((MainActivity)getActivity()).setTextField(selectedItem) use an Interface and everything works nice and I got the same resoult but I am wondering what is better solution here Interface or ((MainActivity)getActivity()).setTextField(selectedItem)?

MainActivity

package com.example.dezox.dijaloglist;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity{

private Button btnStartDialog;
private TextView tvSelectedOption;

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

    initWidgets();
    setupListener();
}

private void initWidgets() {
    btnStartDialog = findViewById(R.id.btnDialog);
    tvSelectedOption = findViewById(R.id.tvselectedOption);
}

private void setupListener() {
    btnStartDialog.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            DijalogX dijalogX = new DijalogX();
            dijalogX.show(getSupportFragmentManager(), "dx");
            tvSelectedOption.setText("");

        }
    });
}



public void setTextField(String odabrano){
    tvSelectedOption.setText(odabrano);
}

public String getTextField(){
    return tvSelectedOption.getText().toString();
}
}

DijalogX

package com.example.dezox.dijaloglist;

import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;


public class DijalogX extends DialogFragment {


    private String[] languageList;



    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initListResource();
    }

    private void initListResource() {
        languageList = getResources().getStringArray(R.array.language_list);
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), 
    android.R.style.Theme_Material_Dialog_Alert)
                .setTitle("Select Language: ")
                .setItems(languageList, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        String selectedItem = languageList[which];





//THIS PART OF THE CODE I DONT UNDERSTAND:
((MainActivity)getActivity()).setTextField(selectedItem);



                    }
                });

        return builder.create();
    }


}
Dezo
  • 835
  • 9
  • 16
  • It means that the person writing it didn't understand how to create interfaces and separate concerns, so he wrote some really bad code you shouldn't be duplicating. – Gabe Sechan Jul 28 '18 at 23:37
  • Here is a start to understand this: https://stackoverflow.com/questions/23414090/what-is-the-difference-between-up-casting-and-down-casting-with-respect-to-class – Kwnstantinos Nikoloutsos Jul 28 '18 at 23:37

1 Answers1

1

You have declared a method in MainActivity called setTextField. If you called

Activity a = getActivity();

you would not be able to call your custom method (it is on your derived class, not the base Activity class).

a.setTextField(selectedIte); // WON'T WORK - NO SUCH METHOD

If instead you call

MainActivity ma = (MainActivity)getActivity();

it is now cast as your derived class and you can then call

ma.setTextField(selectedItem);

Doing it in two lines like this is the same as calling the one-liner in your code

((MainActivity)getActivity()).setTextField(selectedItem);

As far as casting vs. an interface, an interface is a bit more flexible of an approach. If you tried to use this fragment in a different activity (not MainActivity) the casting approach would fail. If you are only ever going to use the fragment in this Activity then either would work.

Tyler V
  • 9,694
  • 3
  • 26
  • 52
  • Your answer is very useful, but I have the additional question about this situation: -When I put this code " Activity activity = getActivity(); " and show in Log.v on logCat I get this: "com.example.dezox.dijaloglist.MainActivity@35d9682d", but if I try this without casting "MainActivity ma = getActivity();" I got an error required: com.example.dezox.dijaloglist.MainActivity, found: android.support.v4.app.FragmentActivity. Why getActivity doesn't return clean MainActivity, and why I need casting here? – Dezo Jul 29 '18 at 11:38
  • What the first command prints in the log shows the final form of the object (MainActivity) even through the variable is cast to `Activity`. The second syntax (`MainActivity ma = getActivity();`) is invalid. `getActivity()` returns an `Activity` and it doesn't cast things implicitly. [This](https://stackoverflow.com/questions/23414090/what-is-the-difference-between-up-casting-and-down-casting-with-respect-to-class) has some good reading to help too. – Tyler V Jul 29 '18 at 14:23