我正在关注Udacity的“开发Android应用”课程,到目前为止该课程还不错。
只是为了尝试新事物,我决定对代码进行一些更改以整理代码。
原始代码基本上包含一个扩展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;
}
}
我还有另外两个班:
一种从服务器获取纯JSON的代码
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转换为String [](
ApiConverter
类)。我跳过了这一细节,因为它工作得很好。它基本上采用原始JSON字符串并返回一个字符串数组。现在,问题是,由于Comm类在另一个线程上完成了其主要工作,因此我必须在Comm.onPostExecute()中更新视图。否则,主线程将在Comm类执行其操作之前执行所有代码,并且我得到一个空字符串。
我曾考虑过将ForecastFragment的onCreateView代码复制到Comm类,但是感觉就像在违反DRY原则。此外,ForecastFragment类已经在实例化Array Adapter的副本,使用复制的代码实例化另一个是浪费资源。
我笨拙地尝试编写代码来获取ForecastFragment的当前实例,但是几乎没有失败。
我还尝试按照here指示将ForecastFragment更改为单例。父Fragment类似乎阻止了我执行此操作(即使我可以做到,但我不确定我是否可以完成我想要的工作)。
我可以将Comm类编写为ForecastFragment的子类,并从那里到达类变量,但是我想知道在保持类分离的同时是否还有更好的方法。
那么,在保持沟通和演讲课分开的情况下,实现此目标的合理方法是什么?
最佳答案
您可以创建接口,该接口具有您要在任务完成时调用的方法
片段应实现此接口
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);
}
}
任务Comm:
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);
}
}