NullPointerException – доступ к представлениям в onCreate ()
Это канонический вопрос для проблемы, часто заданной в StackOverflow.
Я следую учебнику. Я создал новое действие с помощью мастера. Я получаю NullPointerException
при попытке вызвать метод в View
s, полученный с findViewById()
в моей активности onCreate()
.
Активность onCreate()
:
- Привязка данных Android с использованием тега include
- Создание арреалиста объектов
- Фрагмент добавить или заменить не работает
- Android Context.bindService всегда возвращает false, а объект ServiceConnection никогда не запускается
- Как нарисовать круг на canvasе в Android?
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); View something = findViewById(R.id.something); something.setOnClickListener(new View.OnClickListener() { ... }); // NPE HERE if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new PlaceholderFragment()).commit(); } }
Макет XML ( fragment_main.xml
):
- Как добавить тень и границу на круговом образе viewView?
- Почему добавление OnClickListener внутри onBindViewHolder из RecyclerView.Adapter считается плохой практикой?
- Добавление элементов управления яркостью экрана в приложение для Android
- Использование шаблона проектирования Singleton для SQLiteDatabase
- Ошибка сборки тестов для Android: несколько файлов dex определяют Landroid / support / test / BuildConfig
- Как получить частоту от результата fft?
- Использование акселерометра, гироскопа и компаса для расчета движения устройства в 3D-мире
- Сравнение содержимого StringBuffer с равными
Учебное пособие, вероятно, устарело, пытаясь создать пользовательский интерфейс на основе действий, вместо пользовательского интерфейса на основе fragmentов, который будет использоваться с помощью кода, созданного с помощью мастера.
Представление находится в макете fragmentа ( fragment_main.xml
), а не в макете activity_main.xml
( activity_main.xml
). onCreate()
слишком рано на жизненном цикле, чтобы найти его в иерархии onCreate()
деятельности, и возвращается null
. Вызов метода с null
вызывает NPE.
Предпочтительным решением является переместить код в fragment onCreateView()
, вызывая findViewById()
на раздутом fragmentах rootView
:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); View something = rootView.findViewById(R.id.something); // not activity findViewById() something.setOnClickListener(new View.OnClickListener() { ... }); return rootView; }
В качестве дополнительной заметки макет fragmentа в конечном итоге станет частью иерархии видов деятельности и обнаруживается с помощью операции findViewById()
но только после выполнения транзакции fragmentа. Незавершенные транзакции fragmentов выполняются в super.onStart()
после onCreate()
.
Попробуйте метод OnStart()
и просто используйте
View view = getView().findViewById(R.id.something);
или Объявить любой вид с помощью getView().findViewById
Метод getView().findViewById
в onStart()
Объявите прослушиватель кликов в представлении anyView.setOnClickListener(this);
Попытайтесь переместить свои просмотры доступа методу fragmentа onViewCreated, потому что иногда, когда вы пытаетесь получить доступ к представлениям в методе onCreate, они не отображаются в момент возникновения исключения null-указателя.
@Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); View something = findViewById(R.id.something); something.setOnClickListener(new View.OnClickListener() { ... }); // NPE HERE if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new PlaceholderFragment()).commit(); } }
Согласитесь, это типичная ошибка, потому что люди часто не понимают, как работают Фрагменты, когда они начинают работать над разработкой Android. Чтобы облегчить путаницу, я создал простой примерный код, который я изначально разместил в приложении, остановлен в эмуляторе Android , но я также разместил его здесь.
Примером может служить следующее:
public class ContainerActivity extends FragmentActivity implements ExampleFragment.Callback { @Override public void onCreate(Bundle saveInstanceState) { super.onCreate(saveInstanceState); this.setContentView(R.layout.activity_container); if (saveInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.activity_container_container, new ExampleFragment()) .addToBackStack(null) .commit(); } getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener() { public void onBackStackChanged() { int backCount = getSupportFragmentManager().getBackStackEntryCount(); if (backCount == 0) { finish(); } } }); } @Override public void exampleFragmentCallback() { Toast.makeText(this, "Hello!", Toast.LENGTH_LONG).show(); } }
activity_container.xml:
ExampleFragment:
public class ExampleFragment extends Fragment implements View.OnClickListener { public static interface Callback { void exampleFragmentCallback(); } private Button btnOne; private Button btnTwo; private Button btnThree; private Callback callback; @Override public void onAttach(Activity activity) { super.onAttach(activity); try { this.callback = (Callback) activity; } catch (ClassCastException e) { Log.e(this.getClass().getSimpleName(), "Activity must implement Callback interface.", e); throw e; } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_example, container, false); btnOne = (Button) rootView.findViewById(R.id.example_button_one); btnTwo = (Button) rootView.findViewById(R.id.example_button_two); btnThree = (Button) rootView.findViewById(R.id.example_button_three); btnOne.setOnClickListener(this); btnTwo.setOnClickListener(this); btnThree.setOnClickListener(this); return rootView; } @Override public void onClick(View v) { if (btnOne == v) { Toast.makeText(getActivity(), "One.", Toast.LENGTH_LONG).show(); } else if (btnTwo == v) { Toast.makeText(getActivity(), "Two.", Toast.LENGTH_LONG).show(); } else if (btnThree == v) { callback.exampleFragmentCallback(); } } }
fragment_example.xml:
И это должен быть верный пример, он показывает, как вы можете использовать Activity для отображения fragmentа и обрабатывать события в этом fragmentе. А также, как общаться с содержащейся активностью.
Представление «что-то» находится в fragmentе, а не в активности, поэтому вместо доступа к нему в действии вы должны получить к нему доступ в classе fragmentов, например
В PlaceholderFragment.class
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.fragment_main, container, false); View something = root .findViewById(R.id.something); something.setOnClickListener(new View.OnClickListener() { ... }); return root; }
Вы пытаетесь получить доступ к элементам пользовательского интерфейса в onCreate()
но слишком рано обращаться к ним, поскольку в представлениях fragmentов может быть создан метод onCreateView()
. onActivityCreated()
надежен для обработки любых действий над ними, так как активность полностью загружена в этом состоянии.
Добавьте в свой файл activity_main.xml следующее:
Поскольку вы объявили свой вид в onCreateView()
fragment_main.xml
, переместите этот fragment кода, где вы получаете NPE в onCreateView()
fragmentа. Это должно решить проблему.
в распространенном выше коде в вопросе возникает проблема: вы используете R.layout.activity_main в методе oncreate, но имя файла xml – «fragment_main.xml», означает, что вы пытаетесь получить представление файла fragment_main.xml который не отображается, поэтому он дает исключение с помощью исключающего указателя. измените код следующим образом:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.fragment_main);// your xml layout ,where the views are View something = findViewById(R.id.something); something.setOnClickListener(new View.OnClickListener() { ... }); // NPE HERE if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new PlaceholderFragment()).commit(); } }
Вы должны помнить, что важно следующее: NullPointerException возникает, когда вы объявили свою переменную и пытаетесь вернуть ее значение, прежде чем назначать ему значение.
Используйте метод onViewCreated () всякий раз, когда вы используете или вызываете представления из fragmentов.
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) View v = view.findViewById(R.id.whatever) }
У меня есть тот же NullPointerException
инициализирующий слушателя после вызова методов findViewById()
onCreate()
и onCreateView()
.
Но когда я использовал onActivityCreated(Bundle savedInstanceState) {...}
он работает. Таким образом, я мог получить доступ к GroupView
и установить свой прослушиватель.
Надеюсь, это будет полезно.
Самая популярная библиотека для поиска просмотров, которая используется почти каждым разработчиком.
Нож для масла
Как я могу их, достаточно ответов, объясняющих поиск взглядов с помощью правильной методологии. Но если вы разработчик Android и код часто на ежедневной основе, то вы можете использовать масляный нож, который экономит много времени на поиск взглядов, и у вас нет кода для записи. С помощью 2-3 шагов вы можете просматривать просмотры в миллисекундах ,
Добавить зависимость в графе уровня приложения:
implementation 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
Добавить плагин для масляного ножа:
File -> Settings -> plugins->
Затем найдите Android ButterKnife Zelezny и установите плагин и перезапустите свою студию, и вы закончите с ней.
Теперь просто перейдите в метод Oncreate вашей деятельности и щелкните правой кнопкой мыши на своем макете имя и нажмите на кнопку генерации и выберите вариант инъекции butterknife, и ваши ссылки будут автоматически создаваться, как указано ниже:
@BindView(R.id.rv_featured_artist) ViewPager rvFeaturedArtist; @BindView(R.id.indicator) PageIndicator indicator; @BindView(R.id.rv_artist) RecyclerView rvArtist; @BindView(R.id.nsv) NestedScrollingView nsv; @BindView(R.id.btn_filter) Button btnFilter;