getView дочернего фрагмента возвращает значение null

Я создаю и заменяю фрагмент внутри других фрагментов onViewCreated

public void onViewCreated(View view, Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onViewCreated(view, savedInstanceState);
        //add searchFragment to this fragment
        FragmentTransaction fragmentTransaction = getChildFragmentManager().beginTransaction();
        if(searchFragment==null)
            searchFragment=new SearchFragment();
        fragmentTransaction.replace(R.id.updateFragmentContainer, searchFragment).commit();

        if(searchFragment.getView()==null){
            Log.d("getView","of search view is null");//the control always reaches here
        }
        listView=(ListView)getActivity().findViewById(R.id.listView1);
        if(listView!=null)
            listView.setOnItemClickListener(onItemClickListener);//the control never reaches here
        else
            searchFragment.setUpdateItemClickListener(onItemClickListener);//this is a function in the saerchFragment class; there too the listview obtained by findViewbyId is null
    }

Теперь в searchFragment есть listView, onItemClickListener которого я хочу установить в родительском фрагменте. Я пробовал много способов, как показано выше, но ни один из них не работает, так как listView, возвращаемый findViewById, всегда равен нулю.

Кроме того, функция searchFragment отлично работает, когда я удаляю все эти исключения с нулевым указателем, вызванные listView. Я также попытался переопределить getView для searchFragment и вернуть ссылку на представление, которое было изменено во время onCreateView, но оно также вернуло значение null.

РЕДАКТИРОВАТЬ класс SearchFragment

import android.content.ContentProviderClient;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SimpleCursorAdapter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class SearchFragment extends Fragment {
    int rollNo;
    Button searchButton=null;
    EditText rollNoEditText=null;
    ListView listView=null;
    public SearchFragment() {
        // TODO Auto-generated constructor stub
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        return inflater.inflate(R.layout.fragment_search, null);
    }
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        rollNoEditText=(EditText)getView().findViewById(R.id.rollNoEditText1);
        searchButton=(Button)getView().findViewById(R.id.searchbutton1);
        if(searchButton!=null)
            searchButton.setOnClickListener(onClickListener);
        else
            Log.d("Search Button", "null");
        listView=(ListView)getView().findViewById(R.id.listView1);
    }
    View.OnClickListener onClickListener=new View.OnClickListener() {

        @SuppressWarnings("deprecation")
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            if(rollNoEditText.getText().length()>0){
                try{
                rollNo=Integer.parseInt(rollNoEditText.getText().toString());
                if(rollNo>0){
                    listView.setAdapter(
                            new SimpleCursorAdapter(getActivity(), // Context.
                                    R.layout.item_parent_student,
                                    getStudentCurosr(),
                                    new String[] { "name","rollno","class","marks" },
                                    // Parallel array of which template objects to bind to those
                                    // columns.
                                    new int[] {R.id.nameTextView2,R.id.rollNoTextView2,R.id.classTextView2,R.id.marksTextView2 }
                            ));
                }
                    //displayStudentInfo(rollNo);
                }catch(Exception e){
                    e.printStackTrace();
                    Toast.makeText(getActivity().getApplicationContext(), "Please type a valid integer value", Toast.LENGTH_SHORT).show();
                }
            }

        }
    };

    private Cursor getStudentCurosr() {
        // Run query
        Uri uri = Uri.parse("content://com.example.students.provider.studentcontentprovider/student/"+rollNo);
          Log.d("RollNO passed",""+rollNo);
          ContentProviderClient contentProviderClient = getActivity().getContentResolver().acquireContentProviderClient(uri );
          Cursor cur = null;
        try {
            cur = contentProviderClient.query(uri,null,null, null, null);
            return cur;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return cur;
    }


}

person thunderbird    schedule 19.11.2013    source источник


Ответы (1)


getView дочернего фрагмента возвращает значение null

Транзакции фрагментов являются асинхронными, поэтому ваш новый SearchFragment, который вы будете использовать в этой транзакции замены, еще не будет иметь своего представления (это произойдет в будущем после завершения метода onViewCreated()). Вы можете передать экземпляр слушателя во вновь созданный экземпляр SearchFragment и сохранить внутри него в частном поле (в этом установщике вы также можете проверить и посмотреть, доступен ли ListView в этот момент, если он также установлен для прослушивателя) . Затем в одном из методов жизненного цикла SearchFragment (например, onViewCreated()) проверьте это поле OnItemClickListener, если оно null, то установите его в виджете ListView.

Однако что-то подсказывает мне, что вы подходите к этому неправильно, и вы должны позволить SearchFragment установить свой собственный слушатель на ListView и передавать любые события родительскому фрагменту через метод getParentFragment().

person user    schedule 19.11.2013
comment
getChildFragmentManager().executePendingTransactions() у меня не сработало ... я хотел установить его в родительском фрагменте, поскольку я использую фрагмент поиска во многих местах, и не всем из них нужен onItemClicklistener, и реализация варьируется в тех местах, где я его использовал. - person thunderbird; 19.11.2013
comment
@thunderbird Передайте OnItemCLickListener экземпляру searchFragment через метод установки и сохраните его в частном поле. Затем в одном из жизненных циклов SearchFragment (например, onViewCreated()) посмотрите, является ли это поле null, если оно не равно нулю, назначьте его ListView. - person user; 19.11.2013
comment
чертовски крутой чувак... это, наконец, сработало... но будет ли работать каждый раз? Я устанавливаю onItemClickListener сразу после создания объекта фрагмента и сохраняю его в ссылке. Вызывается ли onViewCreated дочернего элемента только после завершения родительского? - person thunderbird; 19.11.2013
comment
@thunderbird Дочерняя транзакция будет выполнена позже, поэтому родительская onViewCreated() будет запущена первой. Если вам нужна дополнительная проверка, в этом установщике также проверьте, является ли ссылка listView нулевой (если она не нулевая, это означает, что представление SearchFragment доступно). Если ссылка не нулевая, также установите OnItemCLickListener в том же установщике. - person user; 19.11.2013
comment
пожалуйста, обновите свой ответ комментарием, чтобы я мог принять его как ответ. - person thunderbird; 20.11.2013