Страница 1 из 1

нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 14 окт 2014, 15:30
sanya5791
Здравствуйте.
при попытке получить доступ к TextView фрагмента, выдается ошибка:
Странно, все работает, когда вставляю 1-й фрагмент. А после замены фрагмента - нет.
Такое впечатление, что после fTrans2.commit(); смена фрагмента происходит не сразу и когда я ищу фрагмент в контейнере, то нахожу предыдущий фрагмент Fragment_main_list.
Помогите разобраться, пожалуйста.

вот ошибка:

Код: Выделить всё

10-14 15:09:59.025: W/dalvikvm(15844): threadid=1: thread exiting with uncaught exception (group=0x4166ece0)
10-14 15:09:59.030: E/AndroidRuntime(15844): FATAL EXCEPTION: main
10-14 15:09:59.030: E/AndroidRuntime(15844): Process: ua.sanya5791.pochemu, PID: 15844
10-14 15:09:59.030: E/AndroidRuntime(15844): java.lang.NullPointerException
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at ua.sanya5791.pochemu.MainActivity.showSubzones(MainActivity.java:516)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at ua.sanya5791.pochemu.MainActivity$3.onItemClick(MainActivity.java:408)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at android.widget.AdapterView.performItemClick(AdapterView.java:298)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at android.widget.AbsListView.performItemClick(AbsListView.java:1113)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at android.widget.AbsListView$PerformClick.run(AbsListView.java:2911)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at android.widget.AbsListView$3.run(AbsListView.java:3645)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at android.os.Handler.handleCallback(Handler.java:733)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at android.os.Handler.dispatchMessage(Handler.java:95)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at android.os.Looper.loop(Looper.java:136)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at android.app.ActivityThread.main(ActivityThread.java:5146)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at java.lang.reflect.Method.invokeNative(Native Method)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at java.lang.reflect.Method.invoke(Method.java:515)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
10-14 15:09:59.030: E/AndroidRuntime(15844): 	at dalvik.system.NativeStart.main(Native Method)
MainActivity.java

Код: Выделить всё

public class MainActivity extends FragmentActivity {
	Fragment frag2;
	Fragment_sub_list fragment_sub_list;
	FragmentTransaction fTrans2;

//создаю 1-й фрагмент, вывожу туда ListView и по нажатию на один из элементов ListView вывожу второй фрагмент в методе showSubzones
........

	protected void showSubzones(int zone_id) {
........ 
		//make new fragment
		fragment_sub_list = new Fragment_sub_list();
		
		//now i can replace current fragment with  fragment_sub_list
		fTrans2 = getSupportFragmentManager().beginTransaction();
		fTrans2.replace(R.id.frgmCont1, fragment_sub_list);
		fTrans2.commit();
		//find fragment
		frag2 = getSupportFragmentManager().findFragmentById(R.id.frgmCont1);	//variant for android.support.v4.app.Fragment library
		
		if (frag2 == null){
			MyLogger("123123: frag2 is null");
		}else{
			MyLogger("showSubzones frag2: " + frag2.toString() );
		}
		
		//set text of TextView in fragment
		TextView tv = 	((TextView) frag2.getView().findViewById(R.id.textView121));
		if (tv == null){
			MyLogger("123123: tv is null" );                     //здесь выдается null
		}else{
			MyLogger("123123 tv: " + tv.toString() );
		}
		tv.setText("Список подзон:");          [b]//////////// здесь происходит ошибка из лога [/b]java.lang.NullPointerException at ua.sanya5791.pochemu.MainActivity.showSubzones(MainActivity.java:516)

Fragment_sub_list.java:

Код: Выделить всё

package ua.sanya5791.pochemu;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment_sub_list extends Fragment {
	public static final boolean isDebug = true;
	public final String TAG = "sanya5791.pochemuchka.Fragment_sub_list";

	@Override
	public View onCreateView(LayoutInflater inflater,
			@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		View view = inflater.inflate(R.layout.fragment_sub_list, null);
		if(view.findViewById(R.id.textView121)==null){
			MyLogger("TextView is NOT found.");
		}else{
			MyLogger("TextView is found.");
		}
		return view;
	}
	
	private void MyLogger(String statement){
		if (isDebug) {
			Log.v(TAG, statement);
		}
	}

}
fragment_sub_list.xml

Код: Выделить всё

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#7700ff00"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView121"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <ListView
        android:id="@+id/lv_out1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

</LinearLayout>

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 14 окт 2014, 15:54
Mikhail_dev
А после замены фрагмента - нет.
смена фрагмента происходит не сразу и когда я ищу фрагмент в контейнере, то нахожу предыдущий фрагмент Fragment_main_list.
А где там замена? Вы создаете первый фрагмент, ищете его и переменную второго фрагмента просто указываете на первый. В итоге две переменные ссылаются на один фрагмент.

Фрагмент и вправду создается не сразу, он создается асихронно. И поэтому
[syntax=java5]tv.setText("Список подзон:"); //////////// здесь происходит ошибка из лога java.lang.NullPointerException at ua.sanya5791.pochemu.MainActivity.showSubzones(MainActivity.java:516) [/syntax]
такие вещи делайте в самом фрагменте, иначе для чего он создавался?

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 14 окт 2014, 17:03
sanya5791
Mikhail_dev писал(а): А где там замена?
Ув. Mikhail_dev. Первый раз я размещал фрагмен в методе onCreate, а затем обращался к элементам первого фрагмента (fragment_main_list) в методе launchCallableStatement и все работало.
Затем в методе showSubzones я сделал замену фрагмента fragment_main_list на fragment_sub_list, после чего не смог обратиться к элементам последнего фрагмента fragment_sub_list.
Вот код MainActivity:

Код: Выделить всё

package ua.sanya5791.pochemu;

public class CopyOfMainActivity extends FragmentActivity implements OnItemClickListener{
	
	Fragment frag1;									//объявим фрагмент
	Fragment_main_list fragment_main_list;
	FragmentTransaction fTrans;

	Fragment frag2;
	Fragment_sub_list fragment_sub_list;
	FragmentTransaction fTrans2;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
		
		fragment_main_list = new Fragment_main_list();
		fTrans = getSupportFragmentManager().beginTransaction();
		fTrans.add(R.id.frgmCont1, fragment_main_list);
		fTrans.commit();

    }

	
	private void launchCallableStatement(String statementName) {

		ListView lv;
.......
				
			case "ZONES_SELECT":

				//find fragment
				frag1 = getSupportFragmentManager().findFragmentById(R.id.frgmCont1);	//variant for android.support.v4.app.Fragment library
				
				//set text of TextView in fragment
				((TextView) frag1.getView().findViewById(R.id.textView11))
					.setText("Список зон:");
				
				// находим список фо фрагменте
				lv = (ListView) frag1.getView().findViewById(R.id.lv_out1);
				
//				ListView lv = (ListView) findViewById(R.id.lv_out1);	//find ListView for current Activity
				// присваиваем адаптер списку
				lv.setAdapter(adapter);
				
				/*** Обработаем нажатие на список ListView ***/
				lv.setOnItemClickListener(new OnItemClickListener() {
					@Override
					public void onItemClick(AdapterView<?> parent, View arg1,
							int position, long arg3) {
						// TODO Auto-generated method stub
						MyLogger("The item N" + position + " is selected" +
								"\nIt's name" + parent.getAdapter().getItem(position));
						try {
							//покажем список подзон для выбранной зоны ("ZONE_ID")
							rs.absolute(position+1);
							showSubzones(rs.getInt("ZONE_ID"));
						} catch (SQLException e) {
							e.printStackTrace();
						}
					}
					
				});
				
 				break;
				
			default:
				break;
			}
	}


	protected void showSubzones(int zone_id) {
		CallableStatement stmt;							//вызываемая процедура БД

		//make new fragment
		fragment_sub_list = new Fragment_sub_list();
		
		//now i can replace current fragment with  fragment_sub_list
		fTrans2 = getSupportFragmentManager().beginTransaction();
		fTrans2.replace(R.id.frgmCont1, fragment_sub_list);
		fTrans2.commit();
		//find fragment
		frag2 = getSupportFragmentManager().findFragmentById(R.id.frgmCont1);	//variant for android.support.v4.app.Fragment library
		
		if (frag2 == null){
			MyLogger("123123: frag2 is null");
		}else{
			MyLogger("showSubzones frag2: " + frag2.toString() );
		}
		//set text of TextView in fragment
		TextView tv = 	((TextView) frag2.getView().findViewById(R.id.textView121));

		if (tv == null){
			MyLogger("123123: tv is null" );
		}else{
			MyLogger("123123 tv: " + tv.toString() );
		}
		
		tv.setText("Список подзон:");
	}


	private void MyLogger(String statement){
		if (isDebug) {
			Log.v(TAG, statement);
		}
	}

}
Да, и Вы говорите, что нужно подобные обращения делать внутри фрагмента - спасибо за совет, буду пробовать.

А вопрос остается актуальным: "Почему я не могу обратиться к элементам 2-го фрагмента fragment_sub_list, сразу после совершения транзакций по замене фрагментов?"

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 14 окт 2014, 17:09
Foenix
так они же уничтожаются

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 14 окт 2014, 17:42
sanya5791
Foenix писал(а):так они же уничтожаются
Спасибо, за ответ. Но, прошу поподробнее.... я только учусь :-)

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 14 окт 2014, 18:10
Foenix
я код не смотрела - когда в это вникать. Но еще раз повторю - при замене фрагмента он уничтожается. Все - нет его элементов и прочего, ты не можешь к нему обращаться.

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 14 окт 2014, 18:56
sanya5791
Foenix писал(а):я код не смотрела - когда в это вникать. Но еще раз повторю - при замене фрагмента он уничтожается. Все - нет его элементов и прочего, ты не можешь к нему обращаться.
Спасибо за ответ.
Так я не могу получить доступ к элементам нового фрагмента. понимаю, что если не поместить фрагмент в стек, то после замены старый удалится.

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 14 окт 2014, 19:03
Foenix
почему не можешь?
почитай урок про активити и фрагменты.

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 14 окт 2014, 19:55
sanya5791
На основе урока из этого сайта я и писал код.
А проблема возникает именно после
замены фрагментов.

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 15 окт 2014, 10:53
sanya5791
Да,... много продолбавшись обнаружил следующее:
1. проблема не в смене фрагментов.
2. Если в методе onCreate добавить в контейнер фрагмент и сразу обратиться к элементу TextView.setText(), этого фрагмента, то выдается ошибка NullPointerException.
3. Если в методе onCreate добавлять фрагмент в контейнер. А затем по щелчку кнопки, в методе onMyClick, обращаться к элементу TextView.setText(), этого фрагмента, то все работает.

Уважаемые спецы, проясните ситуацию, пожалуйста.

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 15 окт 2014, 11:23
Mikhail_dev
"Почему я не могу обратиться к элементам 2-го фрагмента fragment_sub_list, сразу после совершения транзакций по замене фрагментов?"
Да,... много продолбавшись обнаружил следующее:
1. проблема не в смене фрагментов.
2. Если в методе onCreate добавить в контейнер фрагмент и сразу обратиться к элементу TextView.setText(), этого фрагмента, то выдается ошибка NullPointerException.
3. Если в методе onCreate добавлять фрагмент в контейнер. А затем по щелчку кнопки, в методе onMyClick, обращаться к элементу TextView.setText(), этого фрагмента, то все работает.
Я писал ранее
Фрагмент и вправду создается не сразу, он создается асихронно. И поэтому
[syntax=java5]tv.setText("Список подзон:"); //////////// здесь происходит ошибка из лога java.lang.NullPointerException at ua.sanya5791.pochemu.MainActivity.showSubzones(MainActivity.java:516) [/syntax]
Суть в том, что вы фрагмент как объект создаете, но он еще не прицепился к активности и не создал свою вьюшку, поэтому вы получите там null. именно поэтому такие операции следует совершать в самом фрагменте, например в методе onActivityCreated. Этот метод означает что и фрагмент жив, и Activity что его содержит, тоже. И в самом фрагменте мы работаем с элементами фрагмента.
Я могу рассказать как сделать так, чтобы можно было получить информацию о полном создании фрагмента и изменять его элементы с активности, но зачем вам учиться неправильному? Так никто не делает.

Re: нет доступа к элементам фрагмента после замены фрагмента

Добавлено: 15 окт 2014, 12:22
sanya5791
Спасибо большое. Буду пробовать Ваш вариант.

Попутно нашел еще вариант в статье "Communicating with Other Fragments"
http://developer.android.com/training/b ... ating.html
а также, нужно внимательнее смотреть урок 106 на этом сайте "Обработка в Activity события из фрагмента"
http://startandroid.ru/ru/uroki/vse-uro ... ivity.html