Java 问题:将大数据传递给第二个活动

Java 问题:将大数据传递给第二个活动,java,android,android-activity,android-4.0-ice-cream-sandwich,Java,Android,Android Activity,Android 4.0 Ice Cream Sandwich,我有一个奇怪的问题。我在网上四处寻找,但没有找到答案。我还是android编程的初学者。让我们开始吧: 我只想用一些数据调用第二个活动。它适用于小数据,但如果数据变大,第二个活动将不显示,第一个活动将完成。 下面是我调用方法的代码: Intent intent = new Intent(ActivitySearch.this,ActivityResults.class); Bundle bundle = new Bundle(); bundle.putParcelableArrayList("d

我有一个奇怪的问题。我在网上四处寻找,但没有找到答案。我还是android编程的初学者。让我们开始吧:

我只想用一些数据调用第二个活动。它适用于小数据,但如果数据变大,第二个活动将不显示,第一个活动将完成。 下面是我调用方法的代码:

Intent intent = new Intent(ActivitySearch.this,ActivityResults.class);
Bundle bundle = new Bundle();
bundle.putParcelableArrayList("data", searchList);
intent.putExtras(bundle);
startActivity(intent);
接收数据的部分并不重要。即使我不尝试读取捆绑包,也不会调用该活动。我用以下几行代码对此进行了测试:

@Override
public void onCreate(Bundle savedInstanceState) {
Log.d("DEBUG","ActivityResult::onCreate()");
super.onCreate(savedInstanceState);
OnCreate()
从未被调用

也许你其中一个有主意。。。 谢谢你的帮助

编辑:至少我忘了:这只发生在ICS下。该应用程序的工作原理与姜饼和弗罗约类似

编辑2:Logcat

10-10 14:49:46.951: D/OpenGLRenderer(21696): Flushing caches (mode 0)
10-10 14:49:47.011: V/ActivityThread(22429): com.example.amazonsearch white listed for hwui
10-10 14:49:50.821: W/IInputConnectionWrapper(21696): showStatusIcon on inactive InputConnection

若你们将大量信息从一个活动传递到另一个活动,那个么可能会使应用程序速度变慢

但是使用全局类来存储变量,使用它可以轻松地获取或设置任何值

在全局文件中声明的

请参阅此链接:


据我记忆所及,直到API-8(Froyo),在通过INTENT传递可包裹对象时,存在一些限制(如1MB)。但是,您可以简单地将您的可包裹数据写入一个文件,并通过bundle将文件路径发送到下一个活动。稍后,编写第二个活动代码,从文件中读取数据,然后将其删除。

我不知道为什么它不能处理大数据,但如果您找不到任何方法来修复它,我建议您使用自定义全局应用程序。(同时检查正确答案以使其生效)

您可能会得到

正如google所建议的,您可以使用静态字段或单例在活动之间共享数据

他们建议“在短时间内共享复杂的非持久用户定义对象”

从你的代码看来,这正是你所需要的

因此,ActivitySearch.class中的代码可能如下所示:

ActivityResults.data = searchList;
Intent intent = new Intent(ActivitySearch.this,ActivityResults.class);
startActivity(intent);
然后,您可以在ActivityResults活动启动后从ActivityResults活动中的任何位置访问ActivityResults.data


对于需要在用户会话之间共享的数据,不建议使用静态字段,因为当应用程序在后台运行时(如果框架需要释放资源),android framework可能会终止并重新启动应用程序进程。在这种情况下,将重新初始化所有静态字段

我更喜欢通过使用枚举来传递大数据。 这种方法的一些优点:

  • 不需要创建单例,您总是有一个枚举实例
  • 数据被适当地封装
  • 引用在活动收到后立即被删除
以下是一个例子:

package com.jyvee.arguments;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

public class SomeActivity extends Activity {

    // Names for the arguments we pass to the
    // activity when we create it
    private final static String ARG_STRING = "ARG_STRING";
    private final static String ARG_INT = "ARG_INT";

    private String stringField;
    private int intField;
    private List<Object> arrayField;

    private enum DataHolder {
        INSTANCE;

        private List<Object> mObjectList;

        public static boolean hasData() {
            return INSTANCE.mObjectList != null;
        }

        public static void setData(final List<Object> objectList) {
            INSTANCE.mObjectList = objectList;
        }

        public static List<Object> getData() {
            final List<Object> retList = INSTANCE.mObjectList;
            INSTANCE.mObjectList = null;
            return retList;
        }
    }

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

        // Get the activity intent if there is a one
        final Intent intent = getIntent();

        // And retrieve arguments if there are any
        if (intent.hasExtra(ARG_STRING)) {
            stringField = intent.getExtras().getString(ARG_STRING);
        }
        if (intent.hasExtra(ARG_INT)) {
            intField = intent.getExtras().getInt(ARG_INT);
        }
        // And we retrieve large data from enum
        if (DataHolder.hasData()) {
            arrayField = DataHolder.getData();
        }

        // Now stringField, intField fields are available
        // within the class and can be accessed directly
    }

    /**
     * /** A static method for starting activity with supplied arguments
     * 
     * @param contextA
     *            context that starts this activity
     * @param stringArg
     *            A string argument to pass to the new activity
     * @param intArg
     *            An int argument to pass to the new activity
     * @param objectList
     *            An object list argument to pass to the new activity
     */
    public static void startActivity(final Context context, final String stringArg, 
            final int intArg, final List<Object> objectList) {

        // Initialize a new intent
        final Intent intent = new Intent(context, SomeActivity.class);

        // To speed things up :)
        intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);

        // And add arguments to the Intent
        intent.putExtra(ARG_STRING, stringArg);
        intent.putExtra(ARG_INT, intArg);

        // Now we put the large data into our enum instead of using Intent extras
        DataHolder.setData(objectList);

        context.startActivity(intent);
    }
}
package com.jyvee.arguments;
导入java.util.List;
导入android.app.Activity;
导入android.content.Context;
导入android.content.Intent;
导入android.os.Bundle;
公共类活动扩展了活动{
//我们传递给
//创建时的活动
私有最终静态字符串ARG\u String=“ARG\u String”;
私有最终静态字符串ARG_INT=“ARG_INT”;
私有字符串字符串字段;
私有int域;
私有列表数组字段;
私有枚举数据持有者{
实例;
私人名单;
公共静态布尔hasData(){
return INSTANCE.mObjectList!=null;
}
公共静态void setData(最终列表objectList){
INSTANCE.mObjectList=objectList;
}
公共静态列表getData(){
最终列表retList=INSTANCE.mObjectList;
INSTANCE.mObjectList=null;
返回列表;
}
}
@凌驾
创建时受保护的void(最终捆绑保存状态){
super.onCreate(savedState);
//获取活动意图(如果有)
最终意图=getIntent();
//并检索参数(如果有)
if(intent.hasExtra(ARG_字符串)){
stringField=intent.getExtras().getString(ARG_字符串);
}
if(intent.hasExtra(ARG_INT)){
intField=intent.getExtras().getInt(ARG_INT);
}
//我们从enum中检索大数据
if(DataHolder.hasData()){
arrayField=DataHolder.getData();
}
//现在可以使用stringField和intField字段
//在类中,并且可以直接访问
}
/**
*/**使用提供的参数启动活动的静态方法
* 
*@param contextA
*启动此活动的上下文
*@param stringArg
*传递给新活动的字符串参数
*@param intArg
*传递给新活动的int参数
*@param objectList
*要传递给新活动的对象列表参数
*/
公共静态void startActivity(最终上下文上下文、最终字符串stringArg、,
最终int intArg,最终列表objectList){
//初始化一个新的意图
最终意图=新意图(上下文,SomeActivity.class);
//加快速度:)
intent.addFlags(intent.FLAG\u活动\u无\u动画);
//并为意图添加参数
intent.putExtra(ARG_字符串,stringArg);
意图.额外支出(ARG_INT,intArg);
//现在,我们将大数据放入enum中,而不是使用Intent extra
DataHolder.setData(objectList);
背景。开始触觉(意图);
}
}

更多信息。

我最近遇到了这个
TransactionTooLargeException
问题,正在寻找一个可能的解决方案来避免它。最后,我找不到任何有用的东西。在大多数答案中,你会发现有人推荐不同的方法来避免这种例外,但没有合适的例子

以下是我为解决此问题所做的工作,
public class ActivityBridge {

    private static final String KEY_ACTIVITY_BRIDGE = "ACTIVITY_BRIDGE";
    private final Context context;
    private SharedPreferences sharedPreferences;


    public ActivityBridge(Context context) {
        this.context = context;

        sharedPreferences = context.getSharedPreferences(KEY_ACTIVITY_BRIDGE, Context.MODE_PRIVATE);
    }


    @SuppressLint("ApplySharedPref")
    public void putData(Bundle bundle, Intent intent) {
        sharedPreferences.edit()
                .putString(
                        intent.toString(),
                        Base64.encodeToString(bundleToBytes(bundle), 0)
                )
                .commit();
    }


    @SuppressLint("ApplySharedPref")
    public Bundle getData(Intent intent) {
        Bundle bundle;
        final String bundleString = sharedPreferences.getString(intent.toString(), "");

        if (TextUtils.isEmpty(bundleString)) {
            return null;
        } else {
            bundle = bytesToBundle(Base64.decode(bundleString, 0));
        }

        sharedPreferences.edit()
                .clear()
                .commit();

        return bundle;
    }


    public byte[] bundleToBytes(Bundle bundle) {
        Parcel parcel = Parcel.obtain();
        parcel.writeBundle(bundle);
        byte[] bytes = parcel.marshall();
        parcel.recycle();
        return bytes;
    }


    public Bundle bytesToBundle(byte[] bytes) {
        Parcel parcel = Parcel.obtain();
        parcel.unmarshall(bytes, 0, bytes.length);
        parcel.setDataPosition(0);
        Bundle bundle = parcel.readBundle(context.getClassLoader());
        parcel.recycle();
        return bundle;
    }
}
         Intent intent = new Intent(ActivityA.this, ActivityB.class);

         Bundle bundle = new Bundle();
         bundle.putString("<KEY>", "<VALUE>");
         new ActivityBridge(ActivityA.this).putData(bundle, intent);

         startActivity(intent);
    Bundle bundle = new ActivityBridge(this).getData(getIntent());