Помощь в передаче списка массивов и разделяемой активности

#android #android-activity #parcelable

#Android #android-активность #разделяемый

Вопрос:

Итак, я гуглил большую часть вчерашнего дня и прошлую ночь и, похоже, просто не могу понять, как передать arraylist в подактивность. Существует множество примеров и фрагментов, передающих примитивные типы данных, но у меня есть arraylist типа address (адрес.java ниже).

Я нашел много информации об этом в stackoverflow и по всему Интернету, но ничего, что привлекло бы много внимания, за исключением примера с геопунктом. Опять же, мне показалось, что они просто разделили объект GeoPoint на два целых числа и передали его. Я не могу этого сделать, потому что мой класс address может расширяться, чтобы включать целые числа, числа с плавающей точкой, что угодно. На данный момент приведенное ниже тестовое приложение состоит всего из двух строк для простоты. Я подумал, что если бы я мог заставить parcelalbe работать с этим, остальное могло бы последовать.

Может ли кто-нибудь опубликовать рабочий пример для ArrayList непримитивного объекта или, возможно, добавить приведенный ниже код, чтобы заставить это работать?

ОБНОВЛЕНИЕ: приведенный ниже код теперь работает после ответов / редактирования. Спасибо!

 /* helloParcel.java */        
       public class helloParcel extends Activity
{
    // holds objects of type 'address' == name and state
    private ArrayList <address> myList;

    @Override
    public void onCreate (Bundle savedInstanceState)
    {
        super.onCreate (savedInstanceState);
        setContentView (R.layout.main);

        Button b1 = (Button) findViewById(R.id.button1);
        b1.setOnClickListener(ocl);

        myList = new ArrayList();
        address frank   = new address ("frank", "florida");
        address mary    = new address ("mary", "maryland");
        address monty   = new address ("monty", "montana");

        myList.add (frank);
        myList.add (mary);
        myList.add (monty);

        // add the myList ArrayList() the the extras for the intent

    }

    OnClickListener ocl = new OnClickListener() 
    {

        @Override
        public void onClick(View v) 
        {
            // fill parceable and launch activity
            Intent intent = new Intent().setClass(getBaseContext (), subActivity.class);

            // for some reason, I remember a posting saying it's best to create a new
            // object to pass.  I have no idea why..
            ArrayList <address> addyExtras = new ArrayList <address>();

            for (int i = 0; i < myList.size(); i  )
                addyExtras.add (myList.get(i));

            intent.putParcelableArrayListExtra ("mylist", addyExtras);
            startActivity(intent);
        }
    };
} 



/* address.java */
  public class address implements Parcelable
{
    private String name;
    private String state;
    private static String TAG = "** address **";

    public address (String n, String s)
    {
        name = n;
        state = s;
        Log.d (TAG, "new address");
    }

    public address (Parcel in)
   {
    Log.d (TAG, "parcel in");
        name = in.readString ();
        state = in.readString ();
   }

    public String getState ()
    {
        Log.d (TAG, "getState()");
        return (state);
    }

    public String getName ()
    {
        Log.d (TAG, "getName()");
        return (name);
    }

    public static final Parcelable.Creator<address> CREATOR
    = new Parcelable.Creator<address>() 
   {
         public address createFromParcel(Parcel in) 
         {
            Log.d (TAG, "createFromParcel()");
             return new address(in);
         }

         public address[] newArray (int size) 
         {
            Log.d (TAG, "createFromParcel() newArray ");
             return new address[size];
         }
    };

    @Override
   public int describeContents ()
   {
        Log.d (TAG, "describe()");
       return 0;
   }

    @Override
   public void writeToParcel (Parcel dest, int flags)
   {
        Log.d (TAG, "writeToParcel");
       dest.writeString (name);
       dest.writeString (state);
   }

}


/* subActivity.java */
  public class subActivity extends Activity
{
    private final String TAG = "** subActivity **";
    private ArrayList <address> myList;

    @Override
    protected void onCreate (Bundle savedInstanceState)
    {
       super.onCreate (savedInstanceState);
       Log.d (TAG, "onCreate() in subActivity");

       setContentView(R.layout.subactivity);
       TextView tv1 = (TextView) findViewById(R.id.tv_sub);

       myList = getIntent().getParcelableArrayListExtra ("mylist");
       Log.d (TAG, "got myList");

       for (int i = 0; i < myList.size (); i  )
       {
        address a = myList.get (i);
        Log.d (TAG, "state:"   a.getState ());
        tv1.setText (a.getName ()   " is from "   a.getState ());
       }

    }

}
  

Комментарии:

1. Отлично!!!!!!!!!!!!! Отлично сработало, я использовал это в первый раз. Спасибо

Ответ №1:

Я вижу здесь ряд проблем:

  1. Зачем использовать addressParcelable? Почему бы не сделать address реализуемым Parcelable, а затем использовать:

     intent.putParcelableArrayListExtra( "addresses", addyExtras );
      
  2. Ваш разделяемый объект должен содержать статический СОЗДАТЕЛЬ. Подробности см. в документации.

  3. На самом деле вы не добавляете никаких дополнительных функций к intent перед вызовом startActivity() . Смотрите пункт 1 для получения предложения здесь.

Я думаю, что вам нужно будет решить все эти проблемы, чтобы заставить его работать.

Комментарии:

1. В какой-то момент я подумал, что мне нужен дополнительный класс (реализующий Parcelable) для преобразования всего объекта заново. Я думаю, что именно оттуда пришел addressParcelable. Я удалил это из кода выше. Я реализовал ваши предложения, хотя, возможно, и не совсем правильно. Не могли бы вы взглянуть, когда у вас будет время? Получаю ошибку нулевого указателя в SubActivity (), которую я сейчас пытаюсь устранить.

2. Я думаю, что вам нужно вызвать GetIntent().getParcelableArrayList («mylist»), а не savedInstanceState.getParcelableArrayList («mylist»);

3. вы имеете в виду getParcelableArrayListExtra()? Пробовал это, но получаю новую ошибку (см. Недавно отредактированный код выше).

4. 🙂 Я думаю, что теперь это работает! Отредактированный выше код — пришлось модифицировать конструктор в классе address

5. Молодцы, что заставили это работать. Я думаю, вы могли бы обойтись без addyExtras и просто иметь intent.putParcelableArrayListExtra («mylist», myList); — что избавило бы вас от перебора списка

Ответ №2:

Это можно сделать НАМНОГО проще, без всей этой мучительной реализации Parcelable ArrayList (но НЕ любое List ) есть Serializable . Итак, вы можете поместить весь список с помощью putExtra() и извлечь его с помощью getSerializableExtra() , как сказал Сэм.

НО я хочу добавить еще одну важную вещь: объект, который хранится в вашем списке массивов, также должен быть реализован Serializable … и все другие сложные объекты, которые может содержать объект (в вашем случае none), также должны это реализовывать (поэтому это рекурсивно — чтобы сериализовать объект, вы должны иметь возможность сериализовать все его поля).

Теперь вы можете спросить себя, зачем внедрять, Serializable вместо Parcelable , когда уже существуют методы для чтения и записи списков массивов parcelables? Что ж… разница в простоте — просто добавьте implements Serializable и необязательно private static final long serialVersionUID = SOME_CONSTANT , и все готово! Вот причина, по которой я никогда не использую Parcelable — вы можете выполнять все эти вещи, используя Serializable буквально 2 строки кода — вместо множества наследований методов и всего такого прочего…

Комментарии:

1. Преимущество Parcelable перед Serializable заключается в том, что это намного быстрее. Если ваш список большой, разница может быть заметной.

Ответ №3:

Вы можете передавать сериализуемые объекты через putExtra. ArrayList реализует Serializable.

Комментарии:

1. Огромная помощь. Спасибо. Можно было бы подумать, что это стало бы более очевидным.

Ответ №4:

Генеральный директор Майк прав!

putExtra() и getSerializable() будет хранить и извлекать ArrayList<> ваши пользовательские объекты, при этом реализация интерфейса не требуется. Сработало для меня!

Комментарии:

1. Извините, я был неправ.. ваш объект должен реализовать Serializable .. но после этого он работает..