0

我有一個動態添加兩個片段的Activity。一個是隱藏的(無視圖)Fragment,它具有setRetainInstance(true)並處理到我的數據庫處理程序的接口。其目的是啓動AsyncTask以從數據庫中獲取數據,並偵聽數據庫處理程序以將其結果返回。然後它將通過另一個監聽器將數據傳回Activity。然後Activity將把數據交給顯示器Fragment,該顯示器內有ListView並且將相應地顯示。在輪流設置非視圖片段偵聽器時活動崩潰

活動:NOT片段活動

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

    }  
} 

我的問題是:旋轉屏幕時,我的代碼崩潰與上SetListener的Search_Hander在一個空指針異常活動。如果我將Activity更改爲FragmentActivity並使用SupportFragmentManager ....這些都不是問題...只需進行這些快速更改即可正常工作(有關現在不推薦使用的onRetainNonConfigurationInstance()SupportFragmentManager覆蓋,它處理所有內容爲你)。

在試圖解決這一問題,我一直是作爲一個Activity,但放在SearchHolder = (Workout_Search_Holder_Fragment) getFragmentManager.findFragmentByTag("search_holder")else的一部分,如果R.id.Content不是null又給Fragment一個標籤,當我最初設置它,如果R.id.Content WAS null 。請參閱上面的註釋代碼。這工作,但創造了另一個問題,onActivityCreated再次啓動,並啓動我的AsyncTask時,我不想要它。我無法發送或檢查savedInstanceState數據包中的變量,因爲setRetainInstance(true)是空的。我知道我做錯了什麼,但無法繞過它。

回答

0

答案是雙重的:

  1. 我需要手動附加Fragments,這個我知道。
  2. 我在錯誤的地方執行我的AsyncTask。這我不知道。

事實證明,我的AsyncTask重新執行作爲OnActivityCreated被再次調用,即使saveInstanceState(true)設置。但是,onCreate不是。通過將撥打方法改爲onCreate,我確保AsyncTask僅被呼叫一次,因爲在Activity娛樂時不會再次呼叫AsyncTask。在活動中,如果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要求我測試的內容是除空在我自己的,這是一件好事,該FragmentSupportManager沒有需要重新連接Fragments。這也有要求我保存ArrayList的作用,我使用ListView ...再次... FragmentSupportManager完成了所有這些工作,而沒有從我那裏推薦。

我仍然很好奇,爲什麼這種行爲是不同的FragmentActivity,因爲它似乎照顧所有這些對我來說,並需要最低的工作量/代碼工作。

1

您正在使用

加(ANDROID.R.id.content,收藏庫)

,同時增加你的片段,而是試圖

加(數據筒,收藏庫, 「search_holder」),它確保您的片段添加了標籤「search_holder」

那麼,你在其他部分也嘗試通過調用

findFragmentByTag()方法

希望這有助於獲得該片段的對象!

+0

我最初試過所有這些....它的工作,但現在片段調用onActivityCreated時,我抓住了Else部分的舊片段。我應該從OnCreate做我的AsyncTask,所以它不會被調用兩次(因爲OnCreate不會再次調用,如果我保留片段,但OnActivityCreated)。我唯一擔心的是,在我的偵聽器被設置爲活動之前,任務可能會完成。有趣的是,如果我使用FragmenyActivity和SupportFragmentManager ...,爲什麼行爲不同呢? – 2014-10-04 03:10:30

+0

你想讓異步任務只執行一次嗎?爲什麼不能在提交事務之前設置監聽器,以便在從分段的oncreate執行異步任務時監聽器將可用?我想知道你說「使用FragmentActivity與SupportFragmentManager時需要NONE」,我還沒有遇到過這種行爲。 – Dinash 2014-10-04 03:50:36

+0

無論屏幕旋轉多少次,只需進行一次活動創建即可。持有者片段用於允許活動在旋轉的情況下保留正在運行的後臺代碼。持有者片段的唯一責任是在我的DataHelper(另一個從opensqlhelper擴展的獨立類)中啓動sql查詢,並將它接收到的結果傳遞給活動。然後該活動將這些結果傳遞給顯示片段以進行顯示。 – 2014-10-04 03:55:38