itsource

특수한 포인터onCreate()의 뷰에 액세스하는 예외

mycopycode 2022. 11. 26. 14:00
반응형

특수한 포인터onCreate()의 뷰에 액세스하는 예외

이것은 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('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.xmlonCreate()은 라이프 이 너무 뷰 수 또, 「액티비티 뷰」의 계층에서는 찾을 수 없습니다.null이 반환됩니다.에서 nullNPE를 사용하다

를 fragment 「는 fragment입니다.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(), 에만 fragment가 실행됩니다. 중인 은 fragment로 됩니다.super.onStart() 후에onCreate().

방법을 시도하고 사용하세요.

View view = getView().findViewById(R.id.something);

any 할 때 anyould any view view are any view.getView().findViewById에 있어서의 방법.

by "클릭 리스너"를 합니다.anyView.setOnClickListener(this);

액세스 뷰를 fragment의 onViewCreated 메서드로 전환합니다.onCreate 메서드로 뷰에 액세스하려고 하면 늘 포인터 예외가 발생할 때 뷰가 렌더링되지 않을 수 있습니다.

 @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 개발을 시작할 때 Fragments가 어떻게 작동하는지 잘 모르기 때문입니다.혼란을 완화하기 위해 원래 Application is stopp in adroid 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_syslog.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>

예: 플래그먼트:

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_fragment.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>

이것은 유효한 예이며 액티비티를 사용하여 fragment를 표시하고 fragment 내의 이벤트를 처리하는 방법을 보여줍니다.또한 포함된 활동과 통신하는 방법도 설명합니다.

뷰 "something"은 fragment화되어 있고 액티비티가 아니기 때문에 액티비티에서 액세스하는 대신 다음과 같이 fragment 클래스에서 액세스해야 합니다.

Placeholder Fragment.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;
}

에서 UI 요소에 액세스하려고 합니다.onCreate()단, fragment뷰는 에서 작성될 수 있기 때문에 액세스하기에는 아직 이르다.onCreateView()방법.그리고.onActivityCreated()method는 액티비티가 이 상태에서 완전히 로드되기 때문에 이들 액션을 처리할 때 신뢰성이 높습니다.

activity_main.xml에 다음 항목을 추가합니다.

<fragment
    android:id="@+id/myFragment"
    android:name="packagename.MainActivity$PlaceholderFragment"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >
</fragment>

에서 뷰를 선언했으므로fragment_main.xml, NPE 를 취득할 수 있는 코드의 일부를,onCreateView()fragment의 메서드.이것으로 문제가 해결됩니다.

위의 질문의 투고 코드에는 문제가 있습니다.즉, oncreate 메서드에서 R.layout.activity_main을 사용하고 있지만 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();
    }
}

중요한 것은 Null Pointer 입니다.변수를 선언하고 값을 할당하기 전에 값을 검색하려고 하면 예외가 발생합니다.

fragment에서 뷰를 사용하거나 호출할 때 onViewCreated() 메서드를 사용합니다.

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제 청취자를 설정해 주세요.

도움이 됐으면 좋겠어요.

거의 모든 개발자가 사용하는 보기를 찾기 위한 가장 인기 있는 라이브러리입니다.

버터나이프

내가 할 수 있는 한 그들은 적절한 방법론과 함께 관점을 찾는 것을 설명하는 충분한 대답이다.하지만 안드로이드 개발자와 매일 코드 작업을 자주 한다면 버터 나이프를 사용하면 뷰 검색에 많은 시간을 절약할 수 있고 코드를 쓸 필요가 없습니다. 2-3단계로 뷰를 밀리초 안에 찾을 수 있습니다.

앱 수준 그라데이션에 종속성 추가:

implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

버터 나이프용 플러그인 추가:

File -> Settings -> plugins-> 

그런 다음 Android ButterKnife Zellezny를 검색하여 플러그인을 설치하고 스튜디오를 재시작하면 됩니다.

이제 액티비티의 Oncreate method로 이동하여 layout_name을 마우스 오른쪽 버튼으로 클릭하고 generate 버튼을 누른 후 버터나이프 주입 옵션을 선택하면 다음과 같이 뷰 참조가 자동으로 생성됩니다.

    @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;

언급URL : https://stackoverflow.com/questions/23653778/nullpointerexception-accessing-views-in-oncreate

반응형