Android 活动克隆之间的 Parcelable 对象

Android Parcelable Object Between Activities Clone

我有一个 class 实现了具有所有必需读写方法的 Parcelable 接口。 这些是我的parcelable对象的重要方法...

...

public News() {
    // Default constructor...
}

@SuppressWarnings("unchecked")
private News(Parcel in) {
    this.feedId = in.readLong();
    this.ownerId = in.readLong();
    this.author = in.readParcelable(User.class.getClassLoader());
    this.ownerUserName = in.readString();
    this.title = in.readString();
    this.content = in.readString();
    this.image = in.readParcelable(NewsImage.class.getClassLoader());
    this.videoUrl = in.readString();
    this.date = in.readString();
    this.tags = in.readArrayList(Hashtag.class.getClassLoader());
    this.ownerNewspaperName = in.readString();
    this.view = in.readString();
    this.applaud = in.readString();
    this.comment = in.readString();
    this.announce = in.readString();
    this.isApplauded = in.readByte() == 1;
    this.isCommented = in.readByte() == 1;
    this.isAnnounced = in.readByte() == 1;
    this.isViewed = in.readByte() == 1;
    this.isHidden = in.readByte() == 1;
    this.isReported = in.readByte() == 1;
}

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

@Override
public void writeToParcel(Parcel dest, int flags) {
    dest.writeLong(this.feedId);
    dest.writeLong(this.ownerId);
    dest.writeParcelable(this.author, flags);
    dest.writeString(this.ownerUserName);
    dest.writeString(this.title);
    dest.writeString(this.content);
    dest.writeParcelable(this.image, flags);
    dest.writeString(this.videoUrl);
    dest.writeString(this.date);
    dest.writeList(this.tags);
    dest.writeString(this.ownerNewspaperName);
    dest.writeString(this.view);
    dest.writeString(this.applaud);
    dest.writeString(this.comment);
    dest.writeString(this.announce);
    dest.writeByte((byte) (this.isApplauded ? 1 : 0));
    dest.writeByte((byte) (this.isCommented ? 1 : 0));
    dest.writeByte((byte) (this.isAnnounced ? 1 : 0));
    dest.writeByte((byte) (this.isViewed ? 1 : 0));
    dest.writeByte((byte) (this.isHidden ? 1 : 0));
    dest.writeByte((byte) (this.isReported ? 1 : 0));
}

public static final Creator<News> CREATOR = new Creator<News>() {
    @Override
    public News createFromParcel(Parcel source) {
        return new News(source);
    }

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

...

我的 activity 包含列表视图和一个包含我的可打包对象的数组列表的数组适配器。单击列表项时,我将特定的 parcelable 对象传递给 DetailActivity,我可以毫无问题地读取 parcelable 对象......直到现在一切都很完美...... 大问题 从这里开始...... 当我更改此对象的任何属性(写入)时,我实际上只是更改了克隆而不是先前 activity 列表视图中保存的原始对象。 我认为出现这个问题是因为 Parcelable.Creator returns 来自 parcel 的新对象而不是 god 对象引用。

只是克隆...

我的 NewsDetailActivity.class 我在这个 Activity...

中向对象写入新值
public class NewsDetailActivity extends Activity {

//private static final String TAG = "NewsDetailActivity";

public static final String KEY_NEWS = "news";

public static final String KEY_IS_WILLING_TO_COMMENT = "is_willing_to_comment";

private News news;

private float containerWidth;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_news_detail);

    final ActionBarBuilder builder = new ActionBarBuilder(getActionBar());
    builder.initializeSupportiveProperties();

    final String screenName = getResources().getString(R.string.android) + "/" + getTitle();

    final Tracker tracker = ((PapiroomApplication)getApplication()).getTracker(TrackerName.APP_TRACKER);
    tracker.setScreenName(screenName);
    tracker.send(new HitBuilders.AppViewBuilder().build());

    news = getIntent().getParcelableExtra(KEY_NEWS);

    final boolean isWillingToComment = getIntent().getBooleanExtra(KEY_IS_WILLING_TO_COMMENT, false);

    containerWidth = this.getResources().getDisplayMetrics().widthPixels - 20;

    // Layout initialization
    final ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView1);
    final RoundedImageView imgNewsUser = (RoundedImageView) findViewById(R.id.imgNewsDetailUser);
    final PapiroomTextView txtViewCount = (PapiroomTextView) findViewById(R.id.txtNewsView);
    final PapiroomTextView txtNewspaperName = (PapiroomTextView) findViewById(R.id.txtNewsDetailNewspaperName);
    final PapiroomTextView txtNewsUsername = (PapiroomTextView) findViewById(R.id.txtNewsDetailUsername);
    final PapiroomTextView txtNewsDate = (PapiroomTextView) findViewById(R.id.txtNewsDetailDate);
    final PapiroomTextView txtNewsTitle = (PapiroomTextView) findViewById(R.id.txtNewsDetailTitle);
    final ImageView imgNews = (ImageView) findViewById(R.id.imgNewsDetail);
    final ImageView imgNewsVideo = (ImageView) findViewById(R.id.imgNewsDetailVideo);
    final PapiroomTextView txtNewsContent = (PapiroomTextView) findViewById(R.id.txtNewsDetailContent);
    final PapiroomTextView txtNewsApplaudCount = (PapiroomTextView) findViewById(R.id.txtNewsDetailApplaudCount);
    final PapiroomTextView txtNewsCommentCount = (PapiroomTextView) findViewById(R.id.txtNewsDetailCommentCount);
    final PapiroomTextView txtNewsAnnounceCount = (PapiroomTextView) findViewById(R.id.txtNewsDetailAnnounceCount);
    final FrameLayout containerApplaud = (FrameLayout) findViewById(R.id.layoutApplaud);
    final FrameLayout containerAnnounce = (FrameLayout) findViewById(R.id.layoutAnnounce);
    final FrameLayout containerMore = (FrameLayout) findViewById(R.id.layoutMore);
    final ImageView imgNewsMore = (ImageView) findViewById(R.id.imgMore);
    final ImageView btnNewsDetailComment = (ImageView) findViewById(R.id.btnNewsDetailComment);
    final LinearListView listComment = (LinearListView) findViewById(R.id.listNewsDetailComment);
    final PapiroomAutoCompleteTextView txtNewsDetailComment = (PapiroomAutoCompleteTextView) findViewById(R.id.txtNewsDetailComment);

    final NewsImage image = news != null ? news.getImage() : null;
    final float height = image != null ? calculate(image.getWidth(), image.getHeight()) : 0f;
    if(height >= 2000) imgNews.setScaleType(ScaleType.CENTER_CROP);
    imgNews.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, (int) height));
    imgNews.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            onImageClicked(news);
        }
    });

    if(news.isVideo()) {
        imgNewsVideo.setVisibility(View.VISIBLE);
        imgNewsVideo.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                onImageClicked(news);
            }
        });
    }

    txtNewsContent.setMovementMethod(new PapiroomMovementMethod());

    txtNewsApplaudCount.setText(news.getApplaudCount());
    txtNewsApplaudCount.setOnClickListener(new ApplaudCounterClickListener(this, news));

    txtNewsCommentCount.setText(news.getCommentCount());

    txtNewsAnnounceCount.setText(news.getAnnounceCount());
    txtNewsAnnounceCount.setOnClickListener(new AnnounceCounterClickListener(this, news));

    // Applaud View Imp.
    containerApplaud.setVisibility(news.isHidden() ? View.GONE : View.VISIBLE);
    containerApplaud.setBackgroundResource(news.isApplauded() ? R.drawable.bg_circular_active : R.drawable.bg_circular_passive);
    containerApplaud.setOnTouchListener(new PapiroomButtonOnTouchListener(containerApplaud, new ApplaudButtonClickListener(this, news, containerApplaud, txtNewsApplaudCount, true)));

    // Announce View Imp.
    containerAnnounce.setVisibility(news.isHidden() || news.getAuthor().getUserId() == MainActivity.getUser().getUserId() ? View.GONE : View.VISIBLE);
    containerAnnounce.setBackgroundResource(news.isAnnounced() ? R.drawable.bg_circular_active : R.drawable.bg_circular_passive);
    containerAnnounce.setOnTouchListener(new PapiroomButtonOnTouchListener(containerAnnounce, new AnnounceButtonClickListener(this, news, containerAnnounce, txtNewsAnnounceCount)));

    imgNewsMore.setImageResource(R.drawable.ic_more);
    containerMore.setOnTouchListener(new PapiroomButtonOnTouchListener(containerMore, new MoreButtonClickListener(this, news)));

    //final MentionAdapter adapter = new MentionAdapter(this, new ArrayList<User>());
    //adapter.setNotifyOnChange(true);

    // If comment btn was triggered from previous activity
    if(isWillingToComment) txtNewsDetailComment.requestFocus();

    imgNewsUser.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            goToUserPage(news);
        }
    });

    final MentionTextWatcher watcher = new MentionTextWatcher(null, btnNewsDetailComment);
    txtNewsDetailComment.addTextChangedListener(watcher);

    if(!news.isViewed()) new IncreaseViewCountTask(this, news).execute();

    // Initialization
    final CommentAdapter commentAdapter = new CommentAdapter(this, news.getAuthor().getUserId(), txtNewsDetailComment, news, listComment);
    listComment.setDividerDrawable(null);
    listComment.setAdapter(commentAdapter);

    btnNewsDetailComment.setOnClickListener(new PostCommentButtonClickListener(this, commentAdapter, txtNewsDetailComment, news.getFeedId(), scrollView));

    new GetLastCommentsTask(this, listComment, commentAdapter, news).execute();

    if(news != null) {
        final User author = news.getAuthor();
        PapiroomApplication.getImageLoader().displayImage(author.getProfileImageUrl(), imgNewsUser, PapiroomApplication.getOptionsUser());
        txtViewCount.setText(news.getViewCount());
        txtNewspaperName.setText(author.getNewspaperName() != null ? author.getNewspaperName() : news.getOwnerNewspaperName());
        txtNewsUsername.setText(author.getUsername() != null ? "@" + author.getUsername() : "@" + news.getOwnerUserName());
        txtNewsDate.setText(DateTimeUtils.getFormattedDateString(news.getDate()));
        txtNewsTitle.setText(news.getTitle());
        PapiroomApplication.getImageLoader().displayImage(news.getImage().getURL(), imgNews, PapiroomApplication.getOptionsNews());
        txtNewsContent.setText(Html.fromHtml(news.getContent()));
    }
}

private void onImageClicked(News news) {
    final String videoUrl = news.getVideoUrl();
    final String imageUrl = news.getImage().getURL();
    Intent intent;
    if(news.isVideo()) {
        intent = new Intent(this, WebViewActivity.class);
        intent.putExtra(WebViewActivity.KEY_URL, videoUrl);
    }
    else {
        intent = new Intent(this, FullScreenPhotoActivity.class);
        intent.putExtra(FullScreenPhotoActivity.KEY_URL, imageUrl);
    }
    this.startActivity(intent);
    this.overridePendingTransition(R.anim.activity_open_translate, R.anim.activity_close_scale);
}

private float calculate(int w, int h) {
    if(h > 0) {
        final float scale = (float) h / (float) w;
        final float calculated = (scale > 0f) ? (containerWidth * scale) : 0;
        return (calculated > 2000) ? 2000 : calculated;
    }
    else return 0;
}

private void goToUserPage(News news) {
    // Go To User Page
    final long userId = news.getAuthor().getUserId();
    if(userId != ProfileActivity.userId) {
        final String newspaperName = news.getAuthor().getNewspaperName();
        final Intent intent = new Intent(this, ProfileActivity.class);
        intent.putExtra(ProfileActivity.KEY_UID, userId);
        intent.putExtra(ProfileActivity.KEY_NEWSPAPER_NAME, newspaperName);
        startActivity(intent);
        overridePendingTransition(R.anim.activity_open_translate, R.anim.activity_close_scale);
    }
}

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    final int id = item.getItemId();
    switch (id) {
        case android.R.id.home:
            finish();
            break;
    }
    return super.onOptionsItemSelected(item);
}

@Override
public void finish() {
    super.finish();
    overridePendingTransition(R.anim.activity_open_scale, R.anim.activity_close_translate);
}
}

我该如何解决这个问题?

对不起我的英语:)

我更喜欢使用 BroadcastReceivers