【问题标题】:Parcelable custom object losing instance values when passed with intentParcelable 自定义对象在意图传递时丢失实例值
【发布时间】:2016-01-10 02:52:09
【问题描述】:

我遇到了一个让我完全难以置信的问题。我的自定义对象在通过意图发送到新活动后似乎正在丢失值。为什么一个对象只有在意图传递之后才会丢失其实例变量的值?

我有实现 Parcelable 的自定义对象,用于存储特定数据。

public class Vehicle implements Parcelable, Serializable{
private static final String TAG = "vehicleObject";
public String vehicleType;
public String refID;
public String title;

public HashMap<String, String> reservedSpecs;
public HashMap<String, String> generalSpecs;
public HashMap<String, String> engineSpecs;
public HashMap<String, String> powerTrainSpecs;
public HashMap<String, String> otherSpecs;

public Vehicle(String vehicleType, String year, String make, String model){
    this.refID = UUID.randomUUID().toString();
    this.title = year + " " + make + " " + model;
    this.vehicleType = vehicleType;
    this.reservedSpecs = new HashMap<>();
    this.reservedSpecs.put("year", year);
    this.reservedSpecs.put("make", make);
    this.reservedSpecs.put("model", model);
}

public Vehicle(Parcel source){
    Bundle bundle = source.readBundle(getClass().getClassLoader());
    vehicleType = bundle.getString("vehicleType");
    refID = bundle.getString("refID");
    title = bundle.getString("title");

    reservedSpecs = (HashMap) bundle.getSerializable("reserved");
    generalSpecs = (HashMap) bundle.getSerializable("general");
    engineSpecs = (HashMap) bundle.getSerializable("engine");
    powerTrainSpecs = (HashMap) bundle.getSerializable("power");
    otherSpecs = (HashMap) bundle.getSerializable("other");
}

@Override
public void writeToParcel(Parcel dest, int flags){
    Bundle bundle = new Bundle();
    bundle.putString("vehicleType", vehicleType);
    bundle.putString("refID", refID);
    bundle.putString("title", title);
    bundle.putSerializable("reserved", reservedSpecs);
    bundle.putSerializable("general", generalSpecs);
    bundle.putSerializable("engine", engineSpecs);
    bundle.putSerializable("power", powerTrainSpecs);
    bundle.putSerializable("other", otherSpecs);

    dest.writeBundle(bundle);
}

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

/**
  *Generic getters/Setters for all instance variables 
**/

/**
 * Creator required for class implementing the parcelable interface.
 */
public static final Parcelable.Creator<Vehicle> CREATOR = new Creator<Vehicle>() {

    @Override
    public Vehicle createFromParcel(Parcel source) {
        return new Vehicle(source);
    }

    @Override
    public Vehicle[] newArray(int size) {
        return new Vehicle[size];
    }
};

}

然后,在我的主要活动中,使用侦听器传递对象(车辆)。该对象位于 ArrayList 中

public class fragment_overview extends Fragment implements UpdateUI{
    private static final String TAG = "frg_ovrvw";

    private final String SHARED_PREF = "com.kd8bny.maintenanceman_preferences";

    private Toolbar toolbar;
    private Context context;
    private SharedPreferences sharedPreferences;
    private RecyclerView cardList;
    private RecyclerView.LayoutManager cardMan;
    private RecyclerView.Adapter cardListAdapter;

    private ArrayList<Vehicle> roster;
    private String mUnit;

    public fragment_overview() {

    }

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        context = getActivity().getApplicationContext();
        roster = new ArrayList<>(new SaveLoadHelper(context).load());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_overview, container, false);

        sharedPreferences = context.getSharedPreferences(SHARED_PREF, 0);

        //Toolbar
        toolbar = (Toolbar) view.findViewById(R.id.tool_bar);
        ((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
        ((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        ((AppCompatActivity)getActivity()).getSupportActionBar().setHomeButtonEnabled(true);

        //cards
        mUnit = sharedPreferences.getString("prefUnitDist", "");

        cardList = (RecyclerView) view.findViewById(R.id.overview_cardList);
        cardMan = new LinearLayoutManager(getActivity());
        cardList.setLayoutManager(cardMan);
        cardList.addOnItemTouchListener(new RecyclerViewOnItemClickListener(context, cardList, new RecyclerViewOnItemClickListener.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int pos) {
                if (!roster.isEmpty()) { //THIS INTENT HERE
                    Intent viewIntent = new Intent(getActivity(), test.class);
                    Bundle bundle = new Bundle();
                    bundle.putParcelable("vehicle", roster.get(pos));
                    bundle.putInt("pos", pos);
                    viewIntent.putExtra("bundle", bundle);
                    view.getContext().startActivity(viewIntent);
                } else {
                    Intent addIntent = new Intent(getActivity(), activity_add_fleetRoster.class);
                    addIntent.putParcelableArrayListExtra("roster", roster);
                    view.getContext().startActivity(addIntent);
                }
            }

            @Override
            public void onItemLongClick(View view, int pos) {}}));

      return view;

意图发送后,我会在我的新活动中收到它。

public class test extends AppCompatActivity {
private ArrayList<Vehicle> roster;
private Vehicle vehicle;
RecyclerView cardList;
RecyclerView.LayoutManager cardMan;
RecyclerView.Adapter cardListAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);


    Bundle bundle = getIntent().getBundleExtra("bundle");
    vehicle = bundle.getParcelable("vehicle");
    int vehiclePos = bundle.getInt("pos", -1);

    //Set recycler view
    cardList = (RecyclerView) findViewById(R.id.info_cardList);
    cardMan = new LinearLayoutManager(this);
    cardList.setLayoutManager(cardMan);

    }

@Override
public void onResume(){
    super.onResume();

    cardListAdapter = new adapter_info(vehicle);
    cardList.setAdapter(cardListAdapter);
 }

}

然后适配器获取车辆对象并使用 getter 生成卡片

public adapter_info(Vehicle vehicle) {
    ArrayList<HashMap> temp = new ArrayList<>();
    temp.add(vehicle.getGeneralSpecs());
    temp.add(vehicle.getEngineSpecs());
    temp.add(vehicle.getPowerTrainSpecs());
    temp.add(vehicle.getOtherSpecs());       
}
/**
*Adapter stuff such as onCreateViewHodler and bind
**/

现在这一切都很好,第一次运行时花花公子。当我在包括通过另一个意图发送此对象、恢复活动、在我的对象上使用 getter 和 setter 之后尝试做任何事情时。 我的对象中的 Hashmap 失去了它们的值 下面是当您按最近并返回应用程序时发生的情况的 gif 图像。该应用程序永远不会失去焦点。

这是一个显示发生了什么的日志

 01-09 20:27:19.850 2359-2359/com.kd8bny.maintenanceman D/TEST!!!: create{G=G}{E=E}{P=P}{Po=Oo}   //All 4 hashmaps with values
01-09 20:27:19.850 2359-2359/com.kd8bny.maintenanceman A/getGeneralSpecs: get{G=G} //A log of each hashmap in the object's getter method
01-09 20:27:19.850 2359-2359/com.kd8bny.maintenanceman A/getEngineSpecs: get{E=E}
01-09 20:27:19.851 2359-2359/com.kd8bny.maintenanceman A/getPowerTrainSpecs: get{P=P}
01-09 20:27:19.851 2359-2359/com.kd8bny.maintenanceman A/getOtherSpecs: get{Po=Oo}
01-09 20:27:19.851 2359-2359/com.kd8bny.maintenanceman E/adptr_inf: [{G=G}, {E=E}, {P=P}, {Po=Oo}] //Finally what the adapter sees using the getter method
01-09 20:27:19.851 2359-2359/com.kd8bny.maintenanceman E/adptr_inf: [{G=G}, {E=E}, {P=P}, {Po=Oo}]

跑到这里之后,对象又被调用了

    01-09 20:28:13.382 2359-2359/com.kd8bny.maintenanceman A/getGeneralSpecs: get{} //Empty hashmap that had G=G
01-09 20:28:13.382 2359-2359/com.kd8bny.maintenanceman A/getEngineSpecs: get{}  //Empty hashmap that had E=E
01-09 20:28:13.383 2359-2359/com.kd8bny.maintenanceman A/getPowerTrainSpecs: get{}  //Empty hashmap that had P=P
01-09 20:28:13.383 2359-2359/com.kd8bny.maintenanceman A/getOtherSpecs: get{Po=Oo}   //hashmap that retains its value
01-09 20:28:13.383 2359-2359/com.kd8bny.maintenanceman E/adptr_inf: [{Po=Oo}] //And what the adapter sees as it calls on the object again
01-09 20:28:13.383 2359-2359/com.kd8bny.maintenanceman E/adptr_inf: [{Po=Oo}]

为什么这些价值会消失?我可以用不同的方法来解决问题吗?我尝试使用 singeton 并以相同的结果传递可序列化。 提前致谢!

【问题讨论】:

  • 我没有发现问题,但您可以尝试切换到 Parceler,看看是否可以解决问题。 github.com/johncarl81/parceler
  • 有趣的项目。我会试一试
  • 所以我把问题缩小了一点。结果回收站视图表现得很奇怪,因为我将 setAdapter 放在了 onStart 方法中。但是,将我的对象发送到另一个活动时,问题仍然存在。结果 parcelable 工作正常,但我的对象实例在 onResume 方法运行后发生了变化。即丢失数据。

标签: java android object android-intent parcelable


【解决方案1】:

我终于弄清楚了这个问题的问题所在。

JAVA是传值的

每当我创建一个新对象时,我的自定义对象都会传递哈希图的值。然后我将编辑对象或调用它,哈希图将返回其最后一个键/值对。我通过使用 Gson 序列化 hashmap 并稍后将其返回到它的形式解决了这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-12
    • 2018-01-05
    • 1970-01-01
    • 2011-11-15
    相关资源
    最近更新 更多