Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从片段类外部更新视图的arrayAdapter_Java_Android_Android Fragments_Android Studio - Fatal编程技术网

Java 从片段类外部更新视图的arrayAdapter

Java 从片段类外部更新视图的arrayAdapter,java,android,android-fragments,android-studio,Java,Android,Android Fragments,Android Studio,我正在学习Udacity开发Android应用程序的课程,这门课到目前为止还不错 只是为了尝试新事物,我决定对代码做一些修改来整理它 原始代码基本上包含一个扩展了Android的Fragment类的类,该类还包含另一个从openweathermap.org API获取天气数据的类,该类位于一个单独的线程中 我决定将通信、演示和API转换特性转移到不同的类上,因为最初的类太杂乱了(同样,这只是为了自我教育的目的。原始代码工作得很好) 现在我有一个ForecastFragment类: public

我正在学习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;
    }
}
公共类ForecastFragment扩展了片段{
阵列适配器mForecastAdapter;
@凌驾
创建视图上的公共视图(布局、充气机、视图组容器、,
Bundle savedInstanceState){
视图根视图=充气机。充气(R.layout.fragment_main,容器,错误);
//在我们从web获取真实数据之前,这只是一个占位符
字符串[]数据={“正在从服务器获取数据”};
列表预测=新的ArrayList(Arrays.asList(data));
mForecastAdapter=新阵列适配器(
getActivity(),
R.layout.list\u item\u forecast,
R.id.list\u item\u forecast\u textview,
数据);
ListView ListView=(ListView)rootView.findViewById(R.id.listViewForecast);
setAdapter(mForecastAdapter);
返回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
    }
}
公共类通信扩展异步任务{
受保护的字符串doInBackground(字符串…参数){
//网络运营
返回responseFromServer;
}
受保护的void onPostExecute(字符串s){
super.onPostExecute(s);
//下面应该是更新视图的代码
}
}
还有一个将JSON转换为字符串[](
ApiConverter
class)。我跳过了这个的细节,因为它工作得很好。它基本上接受原始JSON字符串并返回字符串数组

现在,问题是,由于Comm类在另一个线程上执行其主要工作,因此我必须更新Comm.onPostExecute()中的视图。否则,在Comm类完成它的工作之前,主线程正在执行所有代码,我得到一个空字符串

我曾想过将ForecastFragment的onCreateView代码复制到Comm类,但感觉好像违反了DRY原则。此外,ForecastFragment类已经在实例化数组适配器的一个副本,用复制的代码实例化另一个副本是浪费资源

我曾笨拙地尝试编写代码来获取ForecastFragment的当前实例,但几乎没有失败

我还尝试按照说明将ForecastFragment更改为singleton。似乎父片段类阻止了我这样做(而且我不确定我是否可以这样做,我是否可以完成我想要的)

我可以将Comm类作为ForecastFragment的子类编写,并从中获取class变量,但我想知道是否有更好的方法保持类之间的分离


那么,在保持沟通课和演示课分开的同时,怎样才能合理地做到这一点呢

您可以创建接口,该接口具有任务完成时要调用的方法

片段应该实现这个接口

AsyncTask应该获取实现此接口的类的实例,在我们的示例中,CALS将是ForecastFragment

在任务中,
onPostExecute()
调用该方法
onTaskComplete()

界面:

public interface TaskCompleteListener {
    public void onTaskComplete(String dataArray);
}
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);
    }
}
预测片段:

public interface TaskCompleteListener {
    public void onTaskComplete(String dataArray);
}
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);
    }
}
公共类ForecastFragment扩展片段实现TaskCompleteListener{
阵列适配器mForecastAdapter;
@凌驾
创建视图上的公共视图(布局、充气机、视图组容器、,
Bundle savedInstanceState){
视图根视图=充气机。充气(R.layout.fragment_main,容器,错误);
//在我们从web获取真实数据之前,这只是一个占位符
//字符串[]数据={“正在从服务器获取数据”};
新命令(this).execute(“参数…”);
返回rootView;
}
@凌驾
公共void onTaskComplete(字符串数据数组){
data=parseJson(dataArray);
列表预测=新的ArrayList(Arrays.asList(data));
mForecastAdapter=新阵列适配器(
getActivity(),
R.layout.list\u item\u forecast,
R.id.list\u item\u forecast\u textview,
数据);
ListView ListView=(ListView)rootView.findViewById(R.id.listViewForecast);
setAdapter(mForecastAdapter);
}
}
任务通信:

public interface TaskCompleteListener {
    public void onTaskComplete(String dataArray);
}
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);
    }
}
公共类通信扩展异步任务{
私有TaskCompleteListener TaskCompleteListener=null;
公用通信(TaskCompleteListener TaskCompleteListener){
this.taskCompleteListener=taskCompleteListener;
}
受保护的字符串doInBackground(字符串…参数){
//网络运营
返回responseFromServer;
}
受保护的void onPostExecute(字符串s){
super.onPostExecute(s);
//下面应该是更新视图的代码
taskCompleteListener.onTaskComplete;
}
}

您可以创建接口,该接口具有任务完成时要调用的方法

片段应该实现这个接口

AsyncTask应该获取实现此接口的类的实例,在我们的示例中,CALS将是ForecastFragment

在任务中,
onPostExecute()
调用该方法
onTaskComplete()

界面:

public interface TaskCompleteListener {
    public void onTaskComplete(String dataArray);
}
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);
    }
}
预测片段:<