1

В приведенном ниже коде я пытаюсь отобразить базовое диалоговое окно при нажатии кнопки. В диалоговом окне показано, что нужно показать некоторый текст. У меня есть работа после того, как я наткнулся на ошибку, но у меня все еще возникает вопрос, почему эта ошибка возникает. В DialogFragmentSubclass.onCreateView() я получаю ссылку на TextView, вызывая findViewById (R.id.someIdValue). Это дает мне NullPointerException. Однако получение справки по телефону:Вызов findViewById() из подкласса DialogFragment дает NullPointerException

View v = inflate.inflate(someREsourceValue, container, fals); 
TextView tv = (TextView) v.findViewById(R.id.someValue); 

, похоже, делает трюк. Почему это работает, а другое дает мне исключение NullPointerException? (Смотрите ниже полный код)

public class MainActivity extends Activity { 
    DownloadImageDialogFragment myDialog; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main_layout); 

     // get reference to buttons 
     Button buttonDownloadImage = (Button) findViewById(R.id.downloadImage); 
     buttonDownloadImage.setText("Download new Image"); 

     // upon button click, show a Dialog 
     buttonDownloadImage.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       // TODO Auto-generated method stub 
       FragmentTransaction ft = getFragmentManager().beginTransaction(); 

       myDialog = new DownloadImageDialogFragment(); 
       myDialog.show(ft, null);    
      } 
     }); 

    } 

    private class DownloadImageDialogFragment extends DialogFragment {    
     @Override 
     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
       Bundle savedInstanceState) { 

       View v = inflater.inflate(R.layout.fragment_dialog, container, false); 
       // TextView tv = findViewById(R.id.dialogTextView); // this gives an error 
       TextView tv = (TextView) v.findViewById(R.id.dialogTextView); // this works 
       tv.setText("This is my dialog"); 
       return v; 
      } 
     } 
} 

А вот файл макета для диалога:

<TextView 
     android:id="@+id/dialogTextView" 
     android:layout_height="wrap_content" 
     android:layout_width="wrap_content" /> 

</LinearLayout> 
+0

Фрагмент - это всего лишь место, где хранитель для просмотра сначала нужно раздуть вид, а затем использовать его. –

ответ

1

Когда вы звоните findViewById(), вы делаете это из внутреннего класса вашего Activity, из которого этот метод исходит. Поскольку этот идентификатор представления не существует в макете вашей деятельности, вы получаете нуль. Ваш фрагмент диалога должен раздуть его макет (как вы уже нашли), прежде чем он сможет получить представления, определенные в нем.

+0

Благодарим вас за четкое объяснение. Это имеет большой смысл! Я полностью забыл о внутренних классах! – Minq

0

Чтобы это объяснить, вам действительно нужно понять, что такое взгляд.

Согласно Android website представления,

занимает прямоугольную область на экране и отвечает за рисование и обработка событий. Вид - это базовый класс для виджетов, которые используются для создания интерактивных компонентов пользовательского интерфейса (кнопки, текстовые поля и т. Д.). Подкласс ViewGroup является базовым классом для макетов, которые являются невидимыми контейнерами, которые содержат другие виды (или другие группы представлений) и определяют их свойства макета.

По существу это класс. Он расширяет Object (базовый класс java) и реализует Drawable.Callback KeyEvent.Callback AccessibilityEventSource. Если вы новичок в JAVA, прочитайте this, чтобы понять implements vs extends.

Теперь, если вы прочитали о функции findViewById(...), вы увидите, что функция возвращает объект View. Это NOT Объект Textview. Так что только вы должны знать, что вам нужно сделать еще один шаг, чтобы заставить базу кода работать.

Теперь, если вы углубитесь и прочитаете страницу Android TextView, вы увидите, что она расширяет класс вида. Таким образом, он наследует все от этого класса. Это в основном, почему вам нужно передать «тип» в представление, которое было возвращено функцией findViewById(int id).

И, наконец, все, о чем вы звоните. Если вы вызываете свою функцию из макета Activity, который не имеет представления, вы получите исключение NULL-указателя, как вы это делали. Я считаю, что в этом случае вы вызывали функцию из подзадачи, которая имеет свой собственный xml и не имеет определенного текстового представления. Поэтому вы должны раздувать представление, которое оно имеет. Добавление этого тега TextView.

+0

Благодарим вас за объяснение.Следующее предложение из вашего ответа - это то, чего я не знал: «Наконец, речь идет о том, где вы вызываете свои функции. Если вы вызываете свою функцию из макета Activity, который не имеет определенного представления, вы получите NULL исключение указателя, как вы. ". Теперь это имеет смысл, и я понимаю его лучше. Thnx! – Minq

 Смежные вопросы

  • Нет связанных вопросов^_^