#android #android-studio #android-layout #android-fragments #android-activity
#Android #android-studio #android-макет #android-фрагменты #android-активность
Вопрос:
Я очень новичок в разработке Android. У меня в основном есть действие с некоторыми кнопками, например, «seeTreePicture» и «seeSeaPicture». Когда я нажимаю кнопку, я хочу использовать фрагмент, который я назвал «ContentViewer», для отображения случайного изображения дерева / моря, а также иметь кнопки под изображением, чтобы уничтожить экземпляр фрагмента ContentViewer и вернуться в меню. Проблема в том, что если я попытаюсь использовать транзакцию фрагмента где-либо, кроме onCreate() действия, я получаю исключение нулевого указателя при попытке получить доступ к представлению во фрагменте.
Моя активность и вещи, связанные с фрагментом:
public class SeeActivity extends AppCompatActivity {
DisplayFragment displayFragment;
Button seeTreeButton;
Button seeSeaButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_see);
seeTreeButton = findViewById(R.id.seeTreeButton);
seeSeaButton = findViewById(R.id.seeSeaButton);
displayFragment = new DisplayFragment();
seeTreeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.fragmentContainer, displayFragment);
fragmentTransaction.commit();
fragmentTransaction.addToBackStack(null);
displayFragment.changeImage(randomTree);
}
});
}
}
В моем фрагменте изменение изображения просто изменяет источник изображения ImageView:
public void changeImage(int treeResource)
{
img = getView().findViewById(R.id.imageView);
img.setImageResource(treeResource);
}
Я получаю исключение с нулевым указателем при попытке получить доступ к представлению из getView() во фрагменте, что означает, что onCreateView не был вызван. Тем не менее, если я помещу ту же транзакцию в метод onCreate() действия, это сработает. Что я делаю не так?
Ответ №1:
Проблема с вашим кодом заключается в том, что вы обращаетесь getView()
к своему фрагменту до того, как фрагмент прошел инициализацию представления. Причина, по которой у вас нет сбоя при выполнении транзакции в onCreate()
методе вашей активности, заключается в том, что к тому времени, когда вы нажимаете на кнопку, ваш фрагмент уже прошел onCreateView()
и инициализировал его просмотр. Ознакомьтесь с руководством по жизненному циклу фрагмента и имейте в виду, что вы не должны получать доступ к вашему представлению фрагмента до его создания или после его уничтожения. Для получения дополнительной информации о том, почему ваш вид фрагмента не инициализируется мгновенно, ознакомьтесь с этим руководством. Что касается решения, рассмотрите возможность установки аргументов для вашего фрагмента, прежде чем добавлять его в свою транзакцию, как здесь:
Bundle args = new Bundle();
args.putInt(DisplayFragment.IMG_RESOURCE_ARG, randomTree);
displayFragment.setArguments(args);
Затем в ваших onCreateView()
onViewCreated()
методах или вашего фрагмента восстановите аргументы, подобные here, и установите ресурс изображения:
@Override
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
int resourceId = requireArguments().getInt(IMG_RESOURCE_ARG);
img = view.findViewById(R.id.imageView);
img.setImageResource(resourceId);
}
Ответ №2:
Потому что транзакция фрагмента не происходит мгновенно. Это происходит асинхронно. Таким образом, фактическая работа по созданию представлений еще не выполнена. Ваши варианты — либо использовать commitNow() вместо commit (который будет выполнять это синхронно, но потребует гораздо больше времени и, возможно, приведет к тому, что ваше приложение будет заметно приостановлено), либо дождаться фактического завершения транзакции фрагмента. Это можно легко сделать, поместив его в Runnable и передав этот runnable в runOnCommit