Как работает интерфейс в Android Studio? - PullRequest
0 голосов
/ 16 октября 2019

Итак, я много читал о создании интерфейсов в приложении для Android, но есть один способ, который я не совсем понимаю. Я включу мои вопросы в код, чтобы вы могли видеть их напрямую. Пожалуйста, будьте вежливы со мной, я новичок и действительно пытаюсь понять это (сидя здесь в течение трех часов на эту одну проблему), но я просто не понимаю. :)

Конструкция следующая:

У меня есть класс MainActivity.java и класс MessageFragment.java. Таким образом, в основном у меня есть фрагмент с видом «Обычный текст» и кнопкой. Когда пользователь вводит что-то в текстовое поле и нажимает кнопку, ввод должен передаваться из фрагмента в MainActivity, и он должен отображаться там на экране. MessageFragment.java выглядит так (извините за длинный код, но я подумал, что вам, возможно, придется увидеть все):

package and import...

public class MessageFragment extends Fragment {

    private EditText editText;
    private Button button;
    OnMessageReadListener messageReadListener;

    public MessageFragment() {
    }

    public interface OnMessageReadListener{
        public void onMessageRead(String message);
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_message, container, false);

        editText = view.findViewById(R.id.text_message);
        button = view.findViewById(R.id.bn);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String message = editText.getText().toString();
                messageReadListener.onMessageRead(message);

???QUESTION 1??? What is the last function doing? It looks to me that it calls the method
onMessageRead() but this method doesn't contain any activity in it's definition.

            }
        });

        return view;
    }

    public void onAttach(Context context){
        super.onAttach(context);

        Activity activity = (Activity) context;
        try{
            messageReadListener = (OnMessageReadListener) activity;
        }catch (ClassCastException e){
            throw new ClassCastException((activity.toString()+" must override OnMessageRead..."));
        }
    }

???QUESTION 2??? What is the whole onAttach method doing? I read things like "Called when 
a fragment is first attached to it's context" but I don't understand this. What is the context here?
And what does the line messageReadListener = (OnMessageReadListener) activity; do?
Also, why does this method come before the "onCreateView" method (it seemed like it while debugging)?

}

, а MainActivity.jave выглядит так:

package and import...

public class MainActivity extends AppCompatActivity implements  MessageFragment.OnMessageReadListener{

    private TextView textView;

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

        if(findViewById(R.id.fragment_container) != null)
        {

            if (savedInstanceState != null){
                return;
            }

            MessageFragment messageFragment = new MessageFragment();
            FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, messageFragment, null);
            fragmentTransaction.commit();
        }
    }

    @Override
    public void onMessageRead(String message) {

        textView = findViewById(R.id.txt_display_message);
        textView.setText(message);

    }

???QUESTION 3??? I really don't get it, when this last method onMessageRead() get's called here.
I know from debugging, that it get's called after I click the button in the fragment, but why?

}

РЕДАКТИРОВАТЬ: Прежде всего, огромное спасибо вам, ребята, за ваши усилия :) Так что, я думаю, я понял это немного яснее, но было бы неплохо, если бы кто-то мог одобрить или не одобрить следующее:

В основном метод onAttach() является связующим звеном между фрагментом и действием. Этот метод гарантирует, что в моем фрагменте есть переменная (messageReadListener), в которой «хранится» MainActivity. Таким образом, метод onCreateView() во фрагменте обрабатывается после метода onAttach(). Таким образом, когда onClickListener во фрагменте срабатывает, строка messageReadListener.onMessageRead(message); в основном говорит MainActivity.onMessageRead(message);, потому что MainActivity уже «хранится» в переменной messageReadListener. И это также причина, по которой вызывается метод onMessageRead() в MainActivity.

Я все еще думаю, что у меня где-то есть ошибка, потому что почему бы мне просто не написать это MainActivity.onMessageRead(message); сразу? И почему бы мне просто не определить метод onMessageRead() непосредственно в MainActivity и получить лишние интерфейсы во фрагменте?

Ответы [ 4 ]

0 голосов
/ 17 октября 2019

Jt очень просто, побег, если вам не нужно знать, что такое интерфейс: интерфейс, как следует из названия, класс между двумя классами, поэтому им не нужно напрямую общаться друг с другом. Почему? Поскольку вы все еще можете не знать, как именно вы хотите обработать событие, вызвавшее функцию интерфейса

Вопрос 1: ему не нужно действие внутри него, действие должно реализовать этот интерфейс, поэтому, когда пользовательнажимает кнопку, что когда-либо это действие сообщало, что метод интерфейса будет выполнен

Я остановлюсь здесь, я отвечу на все остальное, если вы понимаете первый

0 голосов
/ 17 октября 2019

Вы должны создать функцию setOnMessageReadListener во фрагменте и настроить ее в Activity

 public void setOnMessageReadListener(OnMessageReadListener messageReadListener){
    this.messageReadListener = messageReadListener;
}
0 голосов
/ 17 октября 2019

ВОПРОС 1 - Что делает последняя функция? Мне кажется, что он вызывает метод onMessageRead (), но этот метод не содержит никакой активности в своем определении .

Последняя функция - это вызов метода onMessageRead (), который реализует ваш слушатель.

Вы объявили переменную с типом OnMessageReadListener, то есть она реализует метод onMessageRead (String message).

OnMessageReadListener messageReadListener;

....

public interface OnMessageReadListener{
   public void onMessageRead(String message);
}

ВОПРОС 2 - Что делает весь метод onAttach? Я читаю такие вещи, как «Вызывается, когда фрагмент впервые присоединяется к его контексту», но я этого не понимаю. Каков здесь контекст?

Это несколько сбивает с толку, но сводится к жизненному циклу активности андроида .

Система Android вызывает несколько обратных вызовов, когдадействие переходит в новые состояния, чтобы позволить разработчикам действовать в соответствии с этими изменениями состояния.

В этом случае система Android вызывает метод OnAttach, когда фрагмент прикреплен к вашему действию.

 Activity activity = (Activity) context;
 try{
     messageReadListener = (OnMessageReadListener) activity;
 }catch (ClassCastException e){
     throw new ClassCastException();
 }

Как вы видите, здесь происходит то, что разработчик говорит Android: «когда вы присоединяете мой фрагмент к активности cointainer, присвойте переменной messageReadListener значение самой Activity, которая должна реализовывать интерфейс OnMessageReadListener, иначе будет выдано исключение ClassCastException».

ВОПРОС 3 - Я действительно не понимаю, когда этот последний метод onMessageRead () get вызывается здесь.

Он вызывается в вашем ВОПРОСЕ 1код.

  button.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
          String message = editText.getText().toString();
          messageReadListener.onMessageRead(message);
    }
  });

Итак, что здесь происходит?

Разработчик просто использует интерфейсы дляw этот фрагмент для отправки сообщения основной деятельности, когда вы нажимаете кнопку в вашем фрагменте.

Здесь вы говорите: «Я получил переменную, которая содержит все, что реализует интерфейс OnMessageReadListener».

Затем в основном действии вы реализуете этот интерфейс, создав метод onMessageRead ().

Когда Adroid присоединяет фрагмент к основному действию, вы назначаете это действие переменной вашего Фрагмента messageReadListener , ввызов OnAttach.

И после этого вы просто используете эту переменную для вызова при событии кнопки OnClik метода onMessageRead () в основном действии.

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

РЕДАКТИРОВАТЬ: ВОПРОС 4 Я все еще думаю, что у меня естьгде-то ошибка, потому что почему бы мне просто не написать это MainActivity.onMessageRead (message);немедленно? И почему бы мне просто не определить метод onMessageRead () непосредственно в MainActivity и получить лишние интерфейсы во фрагменте?

Вы можете сделать это, но это будет означать, что эти классы получат запутался . То есть вам нужна ссылка на MainActivity в вашем фрагменте.

С помощью интерфейса вы можете использовать свой фрагмент для ANY активности. Он нужен вам только для реализации интерфейса, при любом новом действии, чтобы использовать его.

Так что вам будет проще повторно использовать ваш код, и будет намного понятнее реализовать этот интерфейс в любом действии, которое вы хотите, чтобы ваш фрагмент былчем получить экземпляр каждого действия, в котором вы хотите использовать свой фрагмент, и выяснить, что является вызывающим.

Кодирование интерфейсов считается хорошей практикой дляОбъектно-ориентированное программирование.

0 голосов
/ 16 октября 2019

Мне нравится ваш вопрос, и я собираюсь объяснить его вам в упрощенной форме. Точно так же, как объяснение тому, кто не имеет представления о Java.

Прежде всего, «класс» - это набросок, например, вы хотите построить дом. Во-первых, вам нужен план строительства дома, в Java «класс» - это план, а готовый продукт (в данном случае это дом) - это «объект». Возвращаясь к вашему коду, «MainActivity» - это то, что ваш пользователь видит на экране телефона при открытии приложения, это часть интерфейса. Допустим, вы создали приложение для новостей, например. Когда пользователь открывает приложение новостей, первое, что он видит, это обычно «новости», которые являются вашей «MainActivity». И «расширяется», что будет, например, «Мировые новости». Это означает, что «Мировые новости» являются продолжением «MainActivity», это наследство. В реальной жизни, я уверен, вы иногда слышите, как люди говорят, что вы похожи на свою маму или папу. То же самое, что здесь происходит с «MainActivity» и «extends». «Implements» также является продолжением «MainActivity». Основная причина «реализации» заключается в том, что вы хотите создать более чистый код.

«Переопределение» в реальном мире такое же, как обход. В Java это означает, что «MainActivity» все еще продолжается, но его наследники теперь настроены, хотя они унаследовали свои характеристики, свойства или даже поведение от своего основного родительского объекта «MainActivity». Теперь они независимы, то же самое, что и «новостное приложение». «Новости», могут иметь детей «Мировые новости», «Автомобили», «Политика», «Финансы» и «Погода». Все это новости, они унаследованы от «Новости». Некоторые приложения обычно имеют несколько «MainActivity», в зависимости от размера приложения. Проще говоря, интерфейс - это лицо приложения «News App» в нашем примере, которое пользователь испытывает при использовании приложения. Это более упрощенное объяснение.

Вот простой пример:

@Override
 public void onClick(View v) {

 String enteredText;

 enteredText = mEditText.getText().toString();

 mTextView.setVisibility(View.VISIBLE);
 mTextView.setText(enteredText);

}});

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...