Страницы

Поиск по вопросам

понедельник, 3 февраля 2020 г.

Инициализация View в классе Activity

#android #оптимизация #инициализация


Пытаюсь инициализировать View через метод findViewById(), прямо в классе MainActivity,
чтобы затем, при многократном использовании одного и того же View через onClick, метод
findViewById() не вызывался много раз, но при инициализации прямо в классе MainActivity
приложение вылетает. 

Что я делаю неправильно и как можно один раз инициализировать View для всех последующих
методов?

public class MainActivity extends Activity {    

public View customView = (View) findViewById(R.id.btn);

public void onCustomClick(View view) {
    switch (view.getId()) {
        case R.id.btn:
            customMethod(customView);
            break;
        // и т.д.

    }
}

private void customMethod (View customVar)
{
    // тело метода 
}
}

    


Ответы

Ответ 1



findViewById должно вызываться например в onCreate() методе активити. Т.е. оставьте public View customView; а в onCreate добавьте: customView = (View) findViewById(R.id.btn); UPD. Если копнуть глубже то в Activity у вас в самом начале метода onCreate() есть вызов setContentView(). Это именно этот вызов инициализирует разметку для Activity и только после того как он отработал можно вызывать findViewById(). UPD2. Диаграмма жизненного цикла Activity, спасибо @hardsky за идею, см. http://developer.android.com/training/basics/activity-lifecycle/starting.html Таким образом, исходя из диаграммы, провести инициализацию можно в: onCreate() после setContentView(), в методах onStart() и onResume().

Ответ 2



Ссылки на элементы разметки из .xml будут доступны после того , как этот .xml пройдет инфлейт (inflate) - преобразование из декларативного языка разметки в объекты виджетов. После такого преобразования мы можем получить ссылку на какой либо объект View по его id , заданному в разметке, с помощью метода findViewById(). Следует различать две разных реализации этого метода: Activity.findViewById() - данный метод будет возвращать ссылки на объекты виджетов из разметки только после применения метода активити setContentView() , который свяжет указанную в методе разметку с отображаемым на экране и проведет инфлейт этой разметки в объекты. View.findViewById() - данный метод вернет ссылку на объект виджета по его id , если виджет с таким id присутствует в View. При этом данный View может быть создан динамически - из кода, и тогда ему вообще не требуется инфлейт из XML-разметки , так как мы сразу получаем объекты виджетов, либо пройти инфлейт из XML-разметки отдельно от метода setContentView() , с помощью метода класса LayoutInflater - getLayoutInflater() и метода inflate(). Стоит заметить , что увидеть на экране полученные таким образом View можно будет только после того , как они будут добавлены в разметку , которая указана в методе setContentView(): //контейнер Layout1 присутствует в разметке , подключенной методом setContentView() LinearLayout layout = (LinearLayout) findViewById(R.id.Layout1); //контейнер view1 содержит TextView text1 и будет добавлен в контейнер Layout1 LayoutInflater inflater = getLayoutInflater(); View view1 = inflater.inflate(R.layout.view1, layout, false); TextView text = (TextView) view1.findViewById(R.id.text1); text.setText("Hello"); layout.addView(view1); view1 и text1 изначально не присутствуют в разметке , подключенной методом setContentView() , мы добавляем ее самостоятельно позже , так же устанавливаем значение одному из ее виджетов и только потом переносим в основную разметку , отображаемую на экране Для того, чтобы ссылка на объект (а View это тоже объект в глобальном понимании) была доступна для всех методов в пределах класса (а Activity это тоже класс , в глобальном понимании) необходимо сделать ссылку на этот объект полем класса: public class MainActivity extends Activity { View customView; ... } В коде к такому полю класса следует обращаться только по его имени , без указания класса: //Правильное обращение к полю класса. customView =(View) findViewById(R.id.customView); customView.setText("Hello"); //Неправильное обращение к полю класса. //Данный код создаст ЛОКАЛЬНУЮ переменную с именем, аналогичным имени поля класса , // но она никак не будет связана с полем класса View customView =(View) findViewById(R.id.customView); customView.setText("Hello");

Комментариев нет:

Отправить комментарий