在旋转时设置非视图片段侦听器时活动崩溃

时间:2014-10-03 15:45:10

标签: android android-activity android-fragments fragmentmanager

我有Activity动态添加两个片段。一个是具有Fragment的隐藏(无视图)setRetainInstance(true)并处理我的数据库处理程序的接口。其目的是启动AsyncTask以从数据库中获取数据并监听数据库处理程序以返回其结果。然后它会通过另一个侦听器将数据传回Activity。然后,Activity会将数据传递到显示Fragment的显示ListView,并会相应显示。

活动:不是碎片活动

import android.app.Activity; 
import android.os.Bundle; 

public class Workout_Search_Display_Activity  extends Activity { 
private final String search_string = "SEARCH_STRING"; 
private final String search_type = "SEARCH_TYPE"; 
private String Search_String = ""; 
private String Search_Type = ""; 
private Workout_Search_Holder_Fragment SearchHolder; 
private Workout_Search_Display_Fragment search_display_fragment; 
private Workout_Search_Activity_Listener WSAL; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 

    super.onCreate(savedInstanceState); 

    Search_String =  getIntent().getStringExtra(search_string); 
    Search_Type = getIntent().getStringExtra(search_type); 

    if (getFragmentManager().findFragmentById(android.R.id.content) == null) {
        SearchHolder = Workout_Search_Holder_Fragment.newInstance(Search_String, Search_Type); 
        getFragmentManager().beginTransaction() 
                .add(android.R.id.content, SearchHolder).commit(); 
        search_display_fragment = Workout_Search_Display_Fragment.newInstance(); 
        getFragmentManager().beginTransaction() 
                .add(android.R.id.content, search_display_fragment).commit; 
    } //added too try to fix// else 
     //added to try to fix// SearchHolder = (Workout_Search_Holder_Fragment) getFragmentManager.findFragmentByTag("search_holder");

    WSAL = new Workout_Search_Activity_Listener() { 
        public void NothingFound() { 
            search_display_fragment.no_data(); 

            } 

        public void results_found(ArrayList<Search_Results_Holder> results) { 
        search_display_fragment.is_data(); 
            search_display_fragment.handover_data(results); 

        } 

       }; 
SearchHolder.setListener(WSAL); 
  } 
}

片段:

import android.app.Fragment; 
import android.os.AsyncTask; 
import android.os.Build; 
import android.os.Bundle; 
import android.util.Log; 

public class Workout_Search_Holder_Fragment extends Fragment implements DatabaseHelper.Workout_Search_Listener { 
private String Search_String = ""; 
private String Search_Type = ""; 
private final static String search_string = "SEARCH_STRING"; 
private final static String search_type = "SEARCH_TYPE"; 
private Workout_Search_Activity_Listener listener; 

protected static Workout_Search_Holder_Fragment newInstance( 
        String Search_String, String Search_Type) { 
    Workout_Search_Holder_Fragment f = new Workout_Search_Holder_Fragment(); 

    Bundle args = new Bundle(); 

    args.putString(search_string, Search_String); 
    args.putString(search_type, Search_Type); 
    f.setArguments(args); 
    return f; 
} 

public void onActivityCreated(Bundle savedInstanceState) { 

    super.onActivityCreated(savedInstanceState); 
    setRetainInstance(true); 
    Search_String = getArguments().getString(search_string, null); 
    Search_Type = getArguments().getString(search_type, null); 
    sendSearch(); 
} 

public Workout_Search_Activity_Listener getListener() { 
    return listener; 
} 


public void setListener(Workout_Search_Activity_Listener listener) { 
    this.listener = listener; 
} 
private void sendSearch() { 
    DatabaseHelper.getInstance(getActivity()).getSearchResultsAsync( 
            Search_String, Search_Type, this); 


} 

static public <T> void executeAsyncTask(AsyncTask<T, ?, ?> task, T... params) { 
    if (Build.VERSION.SDK_INT > +Build.VERSION_CODES.HONEYCOMB) { 
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); 

    } else { 
        task.execute(params); 
    } 
} 
@Override 
public void return_no_results_found() { 
    listener.NothingFound(); 
} 
@Override 
public void return_search_results(ArrayList<Search_Results_Holder> results) { 
    Log.v("workout search holder fragment", "results found in fragment, handing off to activity");   
    listener.results_found(results); 

   }     
} 

我的问题是:当旋转屏幕时,我的代码在活动中的Search_Hander的SetListener上以Null Pointer Exception崩溃。如果我将Activity更改为FragmentActivity并使用SupportFragmentManager ....这一切都不是问题...只有那些快速更改才能正常工作(有关现在的事情) -preprecated onRetainNonConfigurationInstance()SupportFragmentManager覆盖,它会为您处理所有事情。

在尝试解决此问题时,我将其保留为Activity,但如果SearchHolder = (Workout_Search_Holder_Fragment) getFragmentManager.findFragmentByTag("search_holder")不是{{1},则将else作为R.id.Content的一部分放入如果null WAS Fragment,我最初设置时会给R.id.Content一个标记。请参阅上面注释掉的代码。这有效,但创建了另一个问题,null再次启动,并在我不想要的时候启动了我的AsyncTask。我无法将onActivityCreated包中的变量发送或检查到片段,因为savedInstanceState为空。我知道我做错了什么,但无法绕过它。

2 个答案:

答案 0 :(得分:1)

您正在使用

  

添加(ANDROID.R.id.content,SearchHolder)

添加片段时,请尝试

  

添加(ContainerID,SearchHolder,&#34; search_holder&#34;),确保您的片段添加了标记&#34; search_holder&#34;

然后就像你在其他部分那样尝试通过调用

获取该片段对象
  

findFragmentByTag()    方法

希望这有帮助!!!

答案 1 :(得分:0)

答案有两个:

  1. 我需要手动附加Fragments,我知道。
  2. 我在错误的区域执行AsyncTask。我不知道。
  3. 事实证明,我的AsyncTask重新执行,因为OnActivityCreated再次被调用,即使设置了saveInstanceState(true)也是如此。但是,onCreate不是。通过将调用方法更改为onCreate,我确保AsyncTask仅被调用一次,因为它不会在Activity重新创建时再次调用。在Activity中,我仍然需要在测试时重置我的两个片段的持有者,如果R.id.content是非null,抓住那些与标签匹配的片段......这是Dinash给出的答案的一部分。

        if (getFragmentManager().findFragmentById(android.R.id.content) == null) {
            SearchHolder = Workout_Search_Holder_Fragment.newInstance(
                    Search_String, Search_Type, false);
            getFragmentManager().beginTransaction()
                    .add(android.R.id.content, SearchHolder, "searchholder")
                    .commit();
            search_display_fragment = Workout_Search_Display_Fragment
                    .newInstance();
            getFragmentManager()
                    .beginTransaction()
                    .add(android.R.id.content, search_display_fragment,
                            "displayholder").commit();
        } else {
            Log.v("activity", "non-null holder");
        SearchHolder = (Workout_Search_Holder_Fragment) getFragmentManager()
                .findFragmentByTag("searchholder");
        search_display_fragment = (Workout_Search_Display_Fragment) getFragmentManager()
                .findFragmentByTag("displayholder");
        }
    
    除了自己重新附加FragmentManager之外,

    Fragments要求我测试内容为空,这是FragmentSupportManager不需要的内容。这也要求我保存我正在为ListView再次使用的ArrayList ... FragmentSupportManager自己完成所有这些操作而不会刺激我。

    我仍然很好奇为什么FragmentActivity的这种行为有所不同,因为它似乎为我照顾所有这些并且需要最少的努力/代码才能工作。