当前位置: 首页 > 知识库问答 >
问题:

Android活动间可打包对象克隆

仲孙翔飞
2023-03-14

我有一个类,它用所有必需的读写方法实现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];
    }
};

...

我的活动包含listview,而arrayadapter包含我的parcelable对象的arraylist。当点击列表项时,我将特定的可解析对象传递给DetailActivity,我可以毫无问题地读取可解析对象...直到现在一切都是完美的…大问题从这里开始..当我更改该对象的任何属性(写入)时,我实际上只是更改了克隆,而不是先前活动列表视图中保留的原始对象。我认为出现这个问题的原因是,Parcelable.Creator从parcel返回一个新对象,而不是god对象引用。

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);
}
}

共有1个答案

邵刚洁
2023-03-14

我更喜欢使用广播接收机

 类似资料:
  • 最近一个面试官问了我一个很棘手的问题。这个问题有几个部分。 为什么(问题是为什么,而不是如何)需要在从一个活动发送到另一个活动时打包对象,而不是直接发送 我给的答案- Parcelable为开发人员提供了限制对象创建的能力,这在某种程度上使其使用速度更快。 我没有得到任何有用的链接后,谷歌,而且我或面试官不太满意的答案。如果你们能帮忙,那就太好了!

  • 假设我有这门课: 以及子类: 我知道这是不可能的,但我想你明白我想要什么。如果Foobar实现了Cloneable,并且没有扩展AbstractFoo,那么子类就可以工作。我想我想要但不允许的是: 如果Foobar实现了Cloneable,并且没有扩展AbstractFoo,那么子类就可以工作。 除了扩展的抽象类,我怎么能做到“相同”?

  • 我正在开发一个由多个活动组成的Android应用程序,我必须在它们之间传递ab对象,但我不能通过使用意图传递它,因为对象的类没有实现可序列化,我怎么做?我无法修改我的类的源代码。谢谢:)

  • 我试图在包含对象ArrayList的类上使用Parcelable。 更新:Station现在也实现了Parcelable,正如Naveen Dew所建议的那样。 车站等级- 当我把图书馆的包裹递给“为声音而制造”服务时,我遇到了一个问题。 java.lang.RuntimeException:无法使用意图启动服务com.tsuryohananov.IsrailiRadio.BackgroundSo

  • 我正在使用一个可打包对象来传递一个意图。我的对象看起来是这样的 公共类配方实现Parcelable{private List Recipe=null;private List firedents=null;private String preparation; 我调试了这部分代码,我知道sendRecipe对象是实例化的,数据是正确的。所以我把这个东西放在意向性上,然后把它发送到下一个活动 在这个

  • 因此,有一个的实例,其中为空,这正是Jackson返回的内容: 我希望json没有空括号: 这个问题对我没有帮助: null