【问题标题】:Put the contents of ArrayList in ArrayAdapter将 ArrayList 的内容放入 ArrayAdapter
【发布时间】:2015-04-21 07:19:10
【问题描述】:

我有一个存储 JSON 内容的 ArrayList 和一个显示它的 ArrayAdapter。现在我正在尝试保存此 JSON 内容,以便用户即使在离线时也能看到它。

我按照这个 SO 问题这样做:How to Cache Parsed JSON for Offline usage 上面的问题让我们将 ArrayList 保存在外部存储的文件中 现在我想在用户离线时启动应用程序时在我的 arrayAdapter 中显示这个存储的 ArrayList 的内容。

到目前为止,这是我的代码,当使用 NullPointerException 离线运行时,应用程序会崩溃

    @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    final View rootView = inflater.inflate(R.layout.fragment_photos, container, false);
    if (isNetworkAvailable()) {

        actorsList = new ArrayList<Actors>();

        new JSONAsyncTask().execute(baseURL);
        listview = (ListView) rootView.findViewById(R.id.list);
        adapter = new ActorAdapter(getActivity(), R.layout.row, actorsList);
        listview.setAdapter(adapter);

    }
 else{

        Toast.makeText(getActivity(), "Network Unavailable. Please Try Again Later ", Toast.LENGTH_LONG).show();

        try {
            Toast.makeText(getActivity(), "Reached TRY ", Toast.LENGTH_LONG).show();
            actorsList = (ArrayList<Actors>)objectFromFile(dataPath);
            //   System.out.print(actorsList);
            for(int i=0;i<actorsList.size();i++)
            {
                Toast.makeText(getActivity(), "Reached FOR ", Toast.LENGTH_LONG).show();
                actor.setName(actorsList.get(i).getName());
                actor.setDescription(actorsList.get(i).getDescription());
                actor.setImage(actorsList.get(i).getImage());
            }

            listview = (ListView) rootView.findViewById(R.id.list);
            adapter = new ActorAdapter(getActivity(), R.layout.row, actorsList);
            listview.setAdapter(adapter);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    return rootView;
}
 class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {


    @Override
    protected void onPreExecute() {

    }

    @Override
    protected Boolean doInBackground(String... urls) {
        try {

            //------------------>>
            HttpGet httppost = new HttpGet(urls[0]);

            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(httppost);

            // StatusLine stat = response.getStatusLine();
            int status = response.getStatusLine().getStatusCode();

            if (status == 200) {
                HttpEntity entity = response.getEntity();
                String data = EntityUtils.toString(entity);


                JSONObject jsono = new JSONObject(data);
                jarray = jsono.getJSONArray("posts");


                for (int i = 0; i < jarray.length(); i++) {
                    JSONObject object = jarray.getJSONObject(i);

                   Actors actor = new Actors();

                    actor.setName(object.getString("title"));
                    actor.setDescription(object.getString("url")); 
                    actor.setImage(object.getString("thumbnail"));                                                        

                    actorsList.add(actor);

                }
                return true;
            }

        } catch (ParseException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return false;
    }

    protected void onPostExecute(Boolean result) {
        dialog.cancel();
        adapter.notifyDataSetChanged();
        if (result) {
            try {
                dataPath = objectToFile(actorsList);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(getActivity().getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
        }
    }
}

如您所见,我正在尝试实现与上面链接的问题中提出的相同的事情,但无法弄清楚如何在离线时显示ArrayList。请帮忙

更新: logcat

04-21 14:23:33.161    4870-4870/info.androidhive.slidingmenu E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: info.androidhive.slidingmenu, PID: 4870
java.lang.RuntimeException: Unable to start activity ComponentInfo{info.androidhive.slidingmenu/info.androidhive.slidingmenu.MainActivity}: java.lang.NullPointerException
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2412)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2470)
        at android.app.ActivityThread.access$900(ActivityThread.java:174)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1307)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:146)
        at android.app.ActivityThread.main(ActivityThread.java:5593)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:515)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
        at dalvik.system.NativeStart.main(Native Method)
 Caused by: java.lang.NullPointerException
        at java.io.File.fixSlashes(File.java:185)
        at java.io.File.<init>(File.java:134)
        at info.androidhive.slidingmenu.ObjectToFileUtil.objectFromFile(ObjectToFileUtil.java:31)
        at info.androidhive.slidingmenu.PagesFragment.onCreateView(PagesFragment.java:176)
        at android.app.Fragment.performCreateView(Fragment.java:1700)
        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:890)
        at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
        at android.app.BackStackRecord.run(BackStackRecord.java:684)
        at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1453)
        at android.app.Activity.performStart(Activity.java:5467)
        at 

android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2385)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2470)
            at android.app.ActivityThread.access$900(ActivityThread.java:174)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1307)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5593)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
            at dalvik.system.NativeStart.main(Native Method)

这是转换 ObjectToFile 和 ObjectFromFile 的类

package info.androidhive.slidingmenu;

import android.os.Environment;

import java.io.*;

 public class ObjectToFileUtil {

public static String objectToFile(Object object) throws IOException {
    String path = Environment.getExternalStorageDirectory() + File.separator + "cache" + File.separator;
    File dir = new File(path);
    if (!dir.exists()) {
        dir.mkdirs();
    }
    path += "data";
    File data = new File(path);
    if (!data.createNewFile()) {
        data.delete();
        data.createNewFile();
    }
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(data));
    objectOutputStream.writeObject(object);
    objectOutputStream.close();
    return path;
}

public static Object objectFromFile(String path) throws IOException, ClassNotFoundException {
    Object object = null;
    File data = new File(path);
    if(data.exists()) {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(data));
        object = objectInputStream.readObject();
        objectInputStream.close();
    }
    return object;
}
}

【问题讨论】:

  • 您需要互联网连接才能第一次获取数据,之后您可以将其存储在 sharedprefrences 或数据库中,当互联网不可用时,您可以从那里获取数据并显示给用户
  • 请显示错误行。对于您的应用概念,您需要将 JSONObject 或 arraylist 存储到数据库或 SharedPreference 中。还将您的适配器设置为 onPostExecute() 方法而不是 onCreateView() method。
  • @PramodYadav 是的,我就是这么做的。首先我用互联网运行应用程序,所有数据都正确加载。然后我关闭 WiFi 并启动(而不是运行)应用程序。但它崩溃了。问题肯定是在 ArrayAdapter 中显示 ArrayList
  • 你得到actorsList = (ArrayList)objectFromFile(dataPath);正确地从这个陈述?
  • 你在吃Reached TRY toast???

标签: android android-listview arraylist android-arrayadapter


【解决方案1】:

更新代码的更新答案

根据这个改变你的 ObjectToFileUtil 类-

public class ObjectToFileUtil {

private static baseFilePath = Environment.getExternalStorageDirectory() + File.separator + "cache" + File.separator+"data";

public static String objectToFile(Object object) throws IOException {
    String path = baseFilePath;
    File dir = new File(path);
    if (!dir.exists()) {
        dir.mkdirs();
    }
    File data = new File(path);
    if (!data.createNewFile()) {
        data.delete();
        data.createNewFile();
    }
    ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(data));
    objectOutputStream.writeObject(object);
    objectOutputStream.close();
    return path;
}

public static Object objectFromFile() throws IOException, ClassNotFoundException {
    String path = baseFilePath;
    Object object = null;
    File data = new File(path);
    if(data.exists()) {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(data));
        object = objectInputStream.readObject();
        objectInputStream.close();
    }
    return object;
}

然后更改以下行 -

actorsList = (ArrayList<Actors>)objectFromFile(dataPath);

到-

actorsList = (ArrayList<Actors>)objectFromFile();

问题的原因

您在网络可用时保存了文件,并将文件路径存储在dataPath 成员中。现在,当您在没有网络可用的情况下启动应用程序时,您正在尝试打开文件,假设该文件已经具有 json.json。到目前为止,一切都很好。但是有一个逻辑错误。查看何时重新启动应用程序,dataPath 中没有任何值,尽管文件可能存在,因为 dataPath 仅在您刚刚写入文件时分配。所以你的路径是null 并且文件对象没有在objectFromFile() 中创建

还要确保您的 Actors 类正在实现 Serializable 接口。导致将对象保存在文件中然后正确检索它,对象需要是Serializable

【讨论】:

  • 你能分享你的日志猫吗? actorList = (ArrayList)objectFromFile(dataPath);你在actorsList这里做什么?
  • 在做更多研究之后,我认为我们首先需要将 ArrayList 保存在 SharedPreferences 中。我正在寻找如何做到这一点。无论如何,添加了我的 logcat 问题
  • 我已经更新了我的Reached Try 代码,现在应用程序没有崩溃。但是除了吐司什么都没有显示。
  • @SwapnaLekshmanan,请参阅保存到 SharedPreferences 只是一个替代选项。从您的 logcat 中可以清楚地看出,NPE 发生在 objectFromFile() 中。您应该共享您的 objectFromFile() 和 objectToFile() 代码。因为问题就在那里。
  • 感谢 Amit.. 我有一个单独的 Java 类 ObjectToFileUtil,它实现了 ObjectToFileObjectFromFile。更新了相关问题
【解决方案2】:

您可以将对象的数组列表转换为字符串并将其存储在 sharedprefrences 中,如下所示:-

 Gson gson = new Gson();
 SharedPreferences sharedPreferences= PreferenceManager.getDefaultSharedPreferences(getActivity());
 SharedPreferences.Editor editor = sharedPreferences.edit();
 editor.putString("list",gson.toJson(actorsList));
 editor.commit();

然后你可以在连接不可用的else块时检索此列表,如下所示:-

SharedPreferences sharedPreferences= PreferenceManager.getDefaultSharedPreferences(getActivity());
String string=sharedPreferences.sharedPreferences.getString("list",null);
List<Actors> list=new List<Actors>();
Type listType = new TypeToken<ArrayList<Actors>>() {
    }.getType();
list= new Gson().fromJson(string, listType);

我在这里使用了 gson 来序列化和反序列化对象,并且不要忘记在你的 gradle 文件中包含 gson

【讨论】:

  • 首先没有冒犯的伙伴。但我不明白你为什么要她保存共享偏好(我知道这应该更容易)。但也有可能,她的业务逻辑是逼着她存到文件里的? json 中不能是大文本响应吗?与其提出不同的解决方案,我们不应该先解决 OP 的问题吗?
  • 我不会强迫她按照我建议的方式去做,我认为这是完全适合她的方式,如果她想通过这种方法来做的话,我不知道有多少大这个列表你永远不知道如果它比从文件中读取太大也不是一个理想的解决方案,那么她必须将它存储在数据库中。我只是在阅读她发布的问题获得的一点知识后回答了这个问题
  • @PramodYadav 我应该用string 替换代码中的objectString 吗?还有我在哪里安排适配器中的列表内容?
猜你喜欢
  • 1970-01-01
  • 2012-09-10
  • 1970-01-01
  • 1970-01-01
  • 2014-02-28
  • 2013-01-12
  • 2018-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多