【问题标题】:Passing JSONObject into another activity将 JSONObject 传递给另一个活动
【发布时间】:2011-02-22 18:16:36
【问题描述】:

我遇到了一个返回 JSON 数据(新的 DVD 标题)的外部 API。我能够解析出 JSON 并将每个 dvd 标题和其他 dvd 信息列出到 ListView 中就好了。我还能够为原始数据(标题字符串)设置一个 onListItemClick 方法。我最终为 onListItemClick 方法写了类似的东西:

请注意,productArray 是一个由另一个方法设置的类 var,该方法包含一个 JSONObjects 数组。

protected void onListItemClick(ListView l, View v, int position, long id) {
    super.onListItemClick(l, v, position, id);

    Intent i = new Intent(DvdListingActivity.this, MovieProductActivity.class);
    try {
        JSONObject jsonObj = productArray.getJSONObject(position);
        i.putExtra("mTitle", jsonObj.getJSONObject("Title").opt("val").toString());
        i.putExtra("mRelDate", jsonObj.getJSONObject("RelDate").opt("val").toString());
        i.putExtra("mDesc", jsonObj.getJSONObject("Desc").opt("val").toString());
        i.putExtra("mRating", jsonObj.getJSONObject("MPAA").getJSONObject("Rating").opt("val").toString());
        i.putExtra("mActors", jsonObj.getJSONObject("Actors").opt("val").toString());
        i.putExtra("mImage", jsonObj.getJSONObject("Image").opt("val").toString());
        startActivity(i);

    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }       

}

上面的代码都有效,但我认为有更好的方法让我将数据传递给另一个活动。我在想我将能够传递一个包含 dvd 电影的所有数据的 JSONObject,而不是单独设置每个数据点。

我尝试了一个半星期来弄清楚如何使用 Parcelable。我尝试实例化一个新的 JSONObject jsonObj,它实现了 Parcelable 但没有运气。我的 LogCat 中不断收到错误消息,提示该对象不可打包。

我已经尝试阅读 Android 开发者网站和其他博客,但我无法将他们的示例应用到我需要做的事情上。

任何帮助将不胜感激

【问题讨论】:

标签: android android-activity parcelable


【解决方案1】:

您可以简单地将整个 JSONObject 作为字符串。像这样的:

i.putString("product", jsonObj.toString);

然后在MovieProductActivity 你可以

JSONObject jsonObj = new JSONObject(getIntent().getStringExtra("product"));

【讨论】:

  • 好主意。我会试试这个
  • 这是我平时做的事情
  • 这也是我所做的。但它可能比使用 parcellable 有额外的开销。
  • 也许吧。但前提是你的对象中有很多数字。否则它将被序列化为 Parcelable impl 中的一组字符串,这显然不是更快/更少的内存消耗。
  • JSONObject jo= new JSONObject(bundle.getString("keyName"));
【解决方案2】:

来自当前活动

Intent mIntent = new Intent(CurrentActivity.this, TargetActivity.class);
mIntent.putExtra("ITEM_EXTRA", json_object.toString());
startActivity(mIntent);

来自目标 Activity 的 onCreate

try {
   json_object = new JSONObject(getIntent().getStringExtra("ITEM_EXTRA"));

   Log.e(TAG, "Example Item: " + json_object.getString("KEY"));

} catch (JSONException e) {
   e.printStackTrace();
}

【讨论】:

  • 最简单的答案,应该是最佳答案!
【解决方案3】:

您可以将有关电影的所有信息封装到一个Movie 对象中,该对象实现了Parcelable

代码看起来与上面类似,但不是传递 6 个不同的额外内容,您可以只传递一个额外内容,即电影。

Movie movie = new Movie();
movie.setTitle(jsonObj.getJSONObject("Title").opt("val").toString());
movie.setRelDat(jsonObj.getJSONObject("RelDate").opt("val").toString());
.
.
.
i.putExtra("movie", movie);

有关实现 Parcelable 对象的信息,请参阅Parcelable docs。你基本上只是写出'writeToParcel'中的每个字符串,并以正确的顺序读入'readFromParcel'中的每个字符串。

【讨论】:

  • 感谢您的回答。那么,您仍然需要将每个对象元素写出到 writeToParcel 方法吗?有没有办法只打包整个对象而不单独设置每个对象元素?
  • 您可以使用 Serializable 代替 Parcelable,但速度明显较慢。如果您不在乎,这是最简单的选择。
  • @Mayra,明显变慢是什么意思?是否注意到用户的加载时间受到影响?
【解决方案4】:

Cheryl Simon 在此处发布的答案是完全正确的,但是对于 android 或 java 新手来说,这可能无法解释得太清楚。请让我以她的回答为基础。

最好和最简洁的方法是使用 Parcelable 界面。

如下声明一个实现 Parcelable 的类。这个使用了实际上没有必要的访问器和修改器。

public class JSonArrayParser implements Parcelable {

    private JSONArray jsonArray;
    public JSonArrayParser() {}

    public JSonArrayParser(JSONArray jsonArray) {
        this.jsonArray = jsonArray;
    }

    public void setJsonArray(JSONArray jsonArray) {
        this.jsonArray = jsonArray;
    }

    public JSONArray getJsonArray() {
        return jsonArray;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {

    }
}

下一步是创建该类的实例(在本例中为 JSonArrayParser)并将其传递给 Bundle,如下例所示。

//这可以是Activity、Fragment、DialogFragment或任何使用Bundle Type的类,如savedInstanceState。

jobItemsPopUp = new JobItemsPopUp();//This example uses a DialogFragment.
Bundle bundle = new Bundle();
JSonArrayParser jSonArrayParser = new JSonArrayParser(jsonArray);
bundle.putParcelable("jsonArray", jSonArrayParser);
jobItemsPopUp.setArguments(bundle);
jobItemsPopUp.show(getActivity().getSupportFragmentManager(), "JobItemsPopUp");

您检索值的方式如下(我使用过 onCreate 但您可以在任何地方检索值):

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        this.jsonArray = ((JSonArrayParser) getArguments().getParcelable("jsonArray")).getJsonArray();
    }
}

作为附加说明:您可以使用自定义构造函数来执行此操作,但此方法已被 Google 弃用。 不推荐使用的旧方法(与 app compat v4 不推荐相关联)是:

private Fragment MyFragment;
MyFragment = new MyFragment(jsonArray)

希望这能有所帮助并解决一些问题。 Parcelable 接口可以与任何带有或不带有修改器和/或访问器的数据类一起使用。

【讨论】:

    【解决方案5】:

    您是否将信息存储在数据库中?如果是,您可以简单地传递所需标题的 ID(通过意图)。

    【讨论】:

    • 那我推荐parcelable的方式
    【解决方案6】:

    看看gson。它允许您将 JSON blob 序列化和反序列化到整个类实例。

    【讨论】:

      【解决方案7】:

      只需像这样创建一个包裹:

      public class Parcel implements Serializable {
      private JSONObject obj;
      
      public Parcel(JSONObject obj) {
          this.obj = obj;
      }
      
      public JSONObject getObj() {
          return obj;
      }}
      

      并放入捆绑包中:

      Parcel p = new Parcel(data);
          Bundle args = new Bundle();
          args.putSerializable("events", p);
      

      最后,您可以使用以下方法取回 JSONObject:

      JSONObject obj = ((Parcel) ((Bundle) getArguments()).getSerializable("events")).getObj();
      

      【讨论】:

        猜你喜欢
        • 2017-12-13
        • 1970-01-01
        • 2017-01-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多