如何在不发送 savedInstanceState 的情况下启动新的 Android 活动?

Posted

技术标签:

【中文标题】如何在不发送 savedInstanceState 的情况下启动新的 Android 活动?【英文标题】:How can I start a new Android activity without sending savedInstanceState? 【发布时间】:2013-11-11 15:27:49 【问题描述】:

我是一名新的 android 开发人员,在开始提供项目列表详细信息的新活动时遇到问题。

我的第一个活动是列出智能手机上安装的所有应用程序。 当我单击此列表中的某个项目时,第二个活动开始显示该项目的详细信息。

但是,我的 onSaveInstanceState 方法(允许我在每次切换智能手机位置时不重新加载应用程序)似乎被发送到详细活动并进入无限循环(或者由于序列化而非常长) ByteBuffer 中的位图)。

我的 PInfo 对象是包含所有应用程序信息(版本、名称、位图)的对象。

public class PInfo implements Serializable

private static final long serialVersionUID = 1L;
private String appname = "";
private String pname = "";
private String versionName = "";
private int versionCode = 0;    
private Bitmap icon ;

private static ByteBuffer dst;
private static byte[] bytesar;

public String getAppname() 
    return appname;

public void setAppname(String appname) 
    this.appname = appname;

public String getPname() 
    return pname;

public void setPname(String pname) 
    this.pname = pname;

public String getVersionName() 
    return versionName;

public void setVersionName(String versionName) 
    this.versionName = versionName;

public int getVersionCode() 
    return versionCode;

public void setVersionCode(int versionCode) 
    this.versionCode = versionCode;

public Bitmap getIcon() 
    return icon;

public void setIcon(Bitmap icon) 
    this.icon = icon;

private void writeObject(ObjectOutputStream out) throws IOException

    out.writeObject(appname);
    out.writeObject(pname);
    out.writeObject(versionName);
    out.writeInt(versionCode);


    out.writeInt(icon.getRowBytes());
    out.writeInt(icon.getHeight());
    out.writeInt(icon.getWidth());

    int bmSize = icon.getRowBytes() * icon.getHeight();
    if(dst==null || bmSize > dst.capacity())
        dst= ByteBuffer.allocate(bmSize);

    out.writeInt(dst.capacity());

    dst.position(0);

    icon.copyPixelsToBuffer(dst);
    if(bytesar==null || bmSize > bytesar.length)
        bytesar=new byte[bmSize];

    dst.position(0);
    dst.get(bytesar);


    out.write(bytesar, 0, bytesar.length);



private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException

    appname=(String) in.readObject();

    pname=(String) in.readObject();
    versionName=(String) in.readObject();
    versionCode= in.readInt();


    int nbRowBytes=in.readInt();
    int height=in.readInt();
    int width=in.readInt();

    int bmSize=in.readInt();



    if(bytesar==null || bmSize > bytesar.length)
        bytesar= new byte[bmSize];


    int offset=0;

    while(in.available()>0)
        offset=offset + in.read(bytesar, offset, in.available());
    


    if(dst==null || bmSize > dst.capacity())
        dst= ByteBuffer.allocate(bmSize);
    dst.position(0);
    dst.put(bytesar);
    dst.position(0);
    icon=Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
    icon.copyPixelsFromBuffer(dst);
    //in.close();

我的列表活动:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_application_list);
    
    if (savedInstanceState != null) 
        apps = (ArrayList<PInfo>) savedInstanceState.getSerializable("apps");
     else 
        apps = new ArrayList<PInfo>();
        apps = getInstalledApps(false);
    
    appAdapter = new AppAdapter(apps);
    setListAdapter(appAdapter);


@Override
protected void onListItemClick(ListView l, View v, int position, long index) 

    AppAdapter appAdapter = new AppAdapter(apps);
    PInfo app = appAdapter.getItem(position);
    Intent intent = new Intent(ApplicationListActivity.this,ApplicationDetailActivity.class);
    //intent.putExtra("app", app);
    intent.putExtra("app_index", index);

    startActivity(intent);



private ArrayList<PInfo> getInstalledApps(boolean getSysPackages) 
    ArrayList<PInfo> res = new ArrayList<PInfo>();        
    List<PackageInfo> packs = getPackageManager().getInstalledPackages(0);
    for(int i=0;i<packs.size();i++) 
        PackageInfo p = packs.get(i);
        if ((!getSysPackages) && (p.versionName == null)) 
            continue ;
        
        PInfo newInfo = new PInfo();
        newInfo.setAppname(p.applicationInfo.loadLabel(getPackageManager()).toString());
        newInfo.setPname(p.packageName);
        newInfo.setVersionName(p.versionName);
        newInfo.setVersionCode(p.versionCode);
        Drawable d = p.applicationInfo.loadIcon(getPackageManager());                
        Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
        newInfo.setIcon(bitmap);
        res.add(newInfo);
    
    return res; 

@Override
protected void onSaveInstanceState(Bundle outState) 
    outState.putSerializable("apps", apps);
    super.onSaveInstanceState(outState);

我的详细活动:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_application_detail);
        
    //PInfo p = (PInfo)getIntent().getExtras().getSerializable("app");
    PackageInfo p = getPackageManager().getInstalledPackages(0).get((int)getIntent().getExtras().getLong("app_index"));
    
    appName = (TextView) findViewById(R.id.appName);
    versionName = (TextView) findViewById(R.id.versionName);
    detailIcon = (ImageView) findViewById(R.id.detailIcon);
    
    appName.setText(p.applicationInfo.loadLabel(getPackageManager()).toString());
    versionName.setText(p.versionName);
    detailIcon.setImageDrawable(p.applicationInfo.loadIcon(getPackageManager()));
    
    

来自 logCat 的部分消息(只是无限循环的一部分;)):

10-31 15:06:53.065: D/dalvikvm(3406): GC_CONCURRENT freed 0K, 20% free 45150K/55751K, paused 12ms+8ms,总共32ms

10-31 15:06:53.065: D/dalvikvm(3406): WAIT_FOR_CONCURRENT_GC 阻塞 20ms

10-31 15:06:53.100: D/dalvikvm(3406): GC_CONCURRENT freed 1013K, 18% free 46177K/55751K, paused 12ms+3ms,总共33ms

10-31 15:06:53.100: D/dalvikvm(3406): WAIT_FOR_CONCURRENT_GC 阻塞 21ms

10-31 15:06:53.115: D/dalvikvm(3406): GC_FOR_ALLOC 释放 0K,18% 释放 46177K/55751K,暂停 13ms,共 13ms

10-31 15:06:53.115:I/dalvikvm-heap(3406):将堆(碎片情况)增加到 47.644MB,分配 2105798 字节

10-31 15:06:53.145: D/dalvikvm(3406): GC_CONCURRENT freed 1027K, 16% free 47206K/55751K, paused 12ms+3ms,总共30ms

10-31 15:06:53.145: D/dalvikvm(3406): WAIT_FOR_CONCURRENT_GC 阻塞 16ms

10-31 15:06:53.160: D/dalvikvm(3406): GC_FOR_ALLOC 释放 0K,16% 释放 47206K/55751K,暂停 15ms,共 15ms

10-31 15:06:53.165:I/dalvikvm-heap(3406):将堆(碎片情况)增加到 50.659MB,分配 4213190 字节

10-31 15:06:53.195: D/dalvikvm(3406): GC_CONCURRENT freed 6664K, 20% free 44656K/55751K, paused 12ms+3ms,总共32ms

10-31 15:06:53.195: D/dalvikvm(3406): WAIT_FOR_CONCURRENT_GC 阻塞 19ms

    我想知道当我开始详细 Activity 时发生了什么? 此循环是否将所有应用程序中的所有位图序列化到 ByteBuffer 中? 如何在不启动此循环的情况下启动我的详细活动?

我希望我已经足够清楚了,对于最终的拼写错误,我深表歉意。

【问题讨论】:

【参考方案1】:

最后,是我的 readObject 和 writeObject 不适合位图的序列化。我找到了另一种方法,但是存在一些性能问题(返回列表需要 4 或 5 秒):Serializing and De-Serializing android.graphics.Bitmap in Java

【讨论】:

以上是关于如何在不发送 savedInstanceState 的情况下启动新的 Android 活动?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不显示确认屏幕的情况下直接发送消息? [复制]

如何在不获取输出的情况下调用发送函数?

如何在不打开短信应用程序的情况下发送短信

如何在不重新发送信息的情况下刷新网页?

如何在不唤醒 Android 屏幕的情况下发送通知

如何在不转义双引号的情况下使用 RestTemplate 发送 JSON 发布请求?