StackOverflow에 자주 게시되는 문제에 대한 표준 질문입니다.
튜토리얼을 따르고 있습니다. 마법사를 사용하여 새 활동을 만들었습니다. 내가 얻을 NullPointerException
에 메서드를 호출 할 때 View
얻을의 findViewById()
내 활동을 onCreate()
.
활동 onCreate()
:
@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
) :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="packagename.MainActivity$PlaceholderFragment" >
<View
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/something" />
</RelativeLayout>
답변
이 튜토리얼은 아마도 마법사가 생성 한 코드가 선호하는 조각 기반 UI 대신 활동 기반 UI를 만들려고 시도한 것 같습니다.
보기가 fragment_main.xml
활동 레이아웃 ( activity_main.xml
)이 아니라 조각 레이아웃 ( )에 있습니다. onCreate()
수명주기에서 너무 일찍 활동보기 계층 구조에서 찾을 수 없으며 a null
가 반환됩니다. 에서 메서드를 호출하면 null
NPE가 발생합니다.
선호되는 해결책은 부풀려진 조각 레이아웃을 onCreateView()
호출 하여 코드를 조각으로 옮기는 것입니다 .findViewById()
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;
}
참고로 조각 레이아웃은 결국 활동보기 계층의 일부가되고 활동으로 검색 할 수 findViewById()
있지만 조각 트랜잭션이 실행 된 후에 만 가능합니다. 보류 조각 트랜잭션이 실행 얻을 super.onStart()
후 onCreate()
.
답변
OnStart()
방법을 시도 하고 사용하십시오
View view = getView().findViewById(R.id.something);
또는 getView().findViewById
방법을 사용하여보기 선언onStart()
보기에서 클릭 리스너 선언 anyView.setOnClickListener(this);
답변
때때로 onCreate 메서드에서 뷰에 액세스하려고 할 때 null 포인터 예외가 발생하는 시점에 렌더링되지 않기 때문에 액세스 뷰를 조각의 onViewCreated 메서드로 전환 해보십시오.
@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 개발 작업을 시작할 때 프래그먼트가 작동하는 방식을 이해하지 못하는 경우가 많기 때문에 이것은 일반적인 오류입니다. 혼란을 줄이기 위해 원래 Application is stops in android emulator 에 게시 한 간단한 예제 코드를 만들었지 만 여기에도 게시했습니다.
예는 다음과 같습니다.
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 :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="@+id/activity_container_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
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 :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/example_button_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="30dp"
android:text="@string/hello"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"/>
<Button
android:id="@+id/example_button_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/example_button_one"
android:layout_alignRight="@+id/example_button_one"
android:layout_below="@+id/example_button_one"
android:layout_marginTop="30dp"
android:text="@string/hello" />
<Button
android:id="@+id/example_button_three"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/example_button_two"
android:layout_alignRight="@+id/example_button_two"
android:layout_below="@+id/example_button_two"
android:layout_marginTop="30dp"
android:text="@string/hello" />
</RelativeLayout>
그리고 그것은 유효한 예제 여야합니다. Activity를 사용하여 Fragment를 표시하고 해당 Fragment에서 이벤트를 처리하는 방법을 보여줍니다. 또한 포함 된 활동과 통신하는 방법도 있습니다.
답변
뷰 “something”은 활동이 아닌 조각에 있으므로 활동에서 액세스하는 대신 다음과 같은 조각 클래스에서 액세스해야합니다.
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()
but 에서 UI 요소에 액세스하려고하는데 , 프래그먼트 뷰에서 onCreateView()
메소드를 만들 수 있으므로 액세스하기에는 너무 이릅니다 . 그리고이 onActivityCreated()
상태에서 활동이 완전히로드되기 때문에 메서드는 모든 작업을 처리 할 수 있습니다.
답변
activity_main.xml에 다음을 추가하십시오.
<fragment
android:id="@+id/myFragment"
android:name="packagename.MainActivity$PlaceholderFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</fragment>