2016-05-16 44 views
0

我正在關注Udacity開發的Android應用程序課程,至今爲止還是相當不錯的。從Fragment類的外部更新視圖的arrayAdapter

只是爲了嘗試新事物,我決定在代碼中進行一些更改以整理它。

原始代碼基本上包含一個擴展Android的Fragment類的類,該類還包含另一個類,用於在單獨的線程中從openweathermap.org API獲取天氣數據。

我決定在單獨的類上移動通信,演示和API轉換功能,因爲它最初太混亂了(再次,這只是爲了自我教育的目的,原始代碼工作得很好)。

現在我有一個ForecastFragment類:

public class ForecastFragment extends Fragment { 

    ArrayAdapter<String> mForecastAdapter; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 

     View rootView = inflater.inflate(R.layout.fragment_main, container, false); 
     //This is just a placeholder until we fetch the real data from web 
     String[] data = {"Fetching data from server"}; 

     List<String> forecast = new ArrayList<String>(Arrays.asList(data)); 

     mForecastAdapter = new ArrayAdapter(
       getActivity(), 
       R.layout.list_item_forecast, 
       R.id.list_item_forecast_textview, 
       data); 

     ListView listView = (ListView) rootView.findViewById(R.id.listViewForecast); 
     listView.setAdapter(mForecastAdapter); 

     return rootView; 
    } 
} 

我有另外兩個其他類:

一個從服務器

public class Comm extends AsyncTask<String, Void, String> { 

    protected String doInBackground(String... params) { 
     //Network operations 
     return responseFromServer; 
    } 

    protected void onPostExecute(String s) { 
     super.onPostExecute(s); 
     //Here should come the code which should update the view 
    } 
} 

而另外一個它轉換得到純JSON JSON轉換爲String [](ApiConverter類)。我在跳過這個細節,因爲它工作得很好。它基本上採用原始的JSON字符串並返回一個字符串數組。

現在,問題是,由於Comm類在另一個線程上完成它的主要工作,我必須更新Comm.onPostExecute()中的視圖。否則,主線程在Comm類執行它的操作之前正在執行所有代碼,並且我得到一個空字符串。

我想將ForecastFragment的onCreateView代碼複製到Comm類中,但感覺就像我違反了DRY原則。此外,ForecastFragment類已經實例化了數組適配器的副本,使用複製的代碼實例化另一個副本會浪費資源。

我已經笨拙地試圖編寫代碼來獲取ForecastFragment的當前實例,但幾乎失敗了。

我也嘗試將ForecastFragment更改爲單例,按照說明here。似乎父母片段課阻止我這樣做(即使我能做到,我也不確定,我可以完成我想要的)。

我可以寫Comm類作爲ForecastFragment的子類並從那裏到達類變量,但我想知道在保持類獨立的情況下是否有更好的方法。

那麼,在保持溝通和演示課程獨立的情況下,完成此項工作的合理方法是什麼?

+0

怎麼樣'通訊class'內創建一個'interface',實現在'fragment'類和'onPostExecute()'方法調用所需的方法,這種方法可以保持獨立班說 –

+0

我這樣做了,我怎麼能在'Comm'類中使用它?我嘗試了幾種方法,但不會編譯。 – SercioSoydanov

+0

我會爲你發佈一些代碼,同時你可以添加你做什麼或者什麼不是編譯? –

回答

1

可以使接口,其中有要打電話的時候,任務完成

的片段應該實現此接口的方法

中的AsyncTask應的類的實例的實現了這個接口,在我們的案例報告將是ForecastFragment。

在任務

onPostExecute()調用該方法onTaskComplete()

接口:

public interface TaskCompleteListener { 
    public void onTaskComplete(String dataArray); 
} 

ForecastFragment:

public class ForecastFragment extends Fragment implements TaskCompleteListener { 

    ArrayAdapter<String> mForecastAdapter; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 

     View rootView = inflater.inflate(R.layout.fragment_main, container, false); 
     //This is just a placeholder until we fetch the real data from web 
     //String[] data = {"Fetching data from server"}; 

     new Comm(this).execute("params..."); 

     return rootView; 
    } 

    @override 
    public void onTaskComplete(String dataArray){ 
     data = parseJson(dataArray); 
     List<String> forecast = new ArrayList<String>(Arrays.asList(data)); 
     mForecastAdapter = new ArrayAdapter(
       getActivity(), 
       R.layout.list_item_forecast, 
       R.id.list_item_forecast_textview, 
       data); 

     ListView listView = (ListView) rootView.findViewById(R.id.listViewForecast); 
     listView.setAdapter(mForecastAdapter); 
    } 
} 

任務通信:

public class Comm extends AsyncTask<String, Void, String> { 
    private TaskCompleteListener taskCompleteListener = null; 

    public Comm(TaskCompleteListener taskCompleteListener){ 
     this.taskCompleteListener = taskCompleteListener; 
    } 

    protected String doInBackground(String... params) { 
     //Network operations 
     return responseFromServer; 
    } 

    protected void onPostExecute(String s) { 
     super.onPostExecute(s); 
     //Here should come the code which should update the view 
     taskCompleteListener.onTaskComplete(s); 
    } 
} 
+0

Eyvallah :)當我回到家時我會嘗試它。只有一個問題:是否可以實現這一點,以便它已經由系統實例化了'ForecastFragment'的特定實例? – SercioSoydanov

+1

Aaaand它的工作。它在實施解決方案時感覺像木匠,但後來我意識到它是多麼的整潔:)非常感謝。順便說一下,在將ForecastFragment實例傳遞給'Comm'類時,我意識到它是已經實例化的實際類。所以現在一切都很好。 – SercioSoydanov

+0

@SercioSoydanov完全一樣,因爲你正在通過'this'而不是'新的預測......'爲你開心:) – Yazan