Android : 조각에 데이터 (추가) 전달


84

저는 Android 프로그래밍이 처음이고 Parcelable의 ArrayList를 조각에 전달하는 동안 문제가 있습니다. 이것은 feedlist 가 parcelable Music 의 ArrayList 인 시작된 (잘 작동하는!) Activity입니다 .

Intent in = new Intent(context, ListMusicsActivity.class);

in.putExtra("arrayMusic", feedList);
activity.startActivity(in);

조각 활동 onCreate () 메서드 :

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activitymusiclist);

    if(savedInstanceState != null)
    {
        ListMusicFragment frag = new ListMusicFragment();
        frag.setArguments(getIntent().getExtras());
    }
}

조각 코드 :

public class ListMusicFragment extends SherlockFragment{

private ArrayList<Music> listMusics = new ArrayList<Music>();
private ListView listMusic;


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
    Bundle savedInstanceState)
{
    listMusics = (ArrayList<Music>) getArguments().getSerializable("arrayMusic");
    View view = inflater.inflate(R.layout.musiclistview, container, false);
    listMusic = (ListView) view.findViewById(R.id.musicListView);
    listMusic.setAdapter(new MusicBaseAdapter(getActivity(), listMusics));

    return view;
}
}

문제가 줄에 있다고 생각합니다

listMusics = (ArrayList<Music>) getArguments().getSerializable("arrayMusic");

마지막으로 이것은 내 음악 수업입니다.

public class Music implements Parcelable{

private String url;
private String artist;
private String title;
private String duration;
private String info_url;
private String lyrics;


public Music(String url, String artist, String title, 
    String duration, String lyrics, String info_url)
{
    this.url = url;
    this.artist = artist;
    this.title = title;
    this.duration = duration;
    this.lyrics = lyrics;
    this.info_url = info_url;
}

public Music(Parcel in)
{
    url = ParcelUtils.readString(in);
    artist = ParcelUtils.readString(in);
    title = ParcelUtils.readString(in);
    duration = ParcelUtils.readString(in);
    info_url = ParcelUtils.readString(in);
    lyrics = ParcelUtils.readString(in);
}

public String getUrl()
{
    return url;
}

public String getArtist()
{
    return artist;
}

public String getTitle()
{
    return title;
}

public String getDuration()
{
    return duration;
}

public String getLyrics()
{
    return lyrics;
}

public String getInfo()
{
    return info_url;
}

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


@Override
public void writeToParcel(Parcel dest, int flags)
{
    ParcelUtils.writeString(dest, url);
    ParcelUtils.writeString(dest, artist);
    ParcelUtils.writeString(dest, title);
    ParcelUtils.writeString(dest, duration);
    ParcelUtils.writeString(dest, lyrics);
    ParcelUtils.writeString(dest, info_url);
}

public static final Parcelable.Creator<Music> CREATOR = 
    new Parcelable.Creator<Music>() {

    public Music createFromParcel(Parcel in)
    {
        return new Music(in);
    }

    public Music[] newArray(int size)
    {
        return new Music[size];
    }
};
}

이 코드를 실행할 때 문제 는 Fragment onCreateView () 메서드java.lang.NullPointerException입니다 . 누군가 내가 어디에서 실패하고 있는지 알기 위해 올바른 방향으로 나를 가리키면 많은 감사를 표할 것입니다.

편집 : 문제 해결 :이 줄을 조각 Activity onCreate () 메서드에 추가해야합니다 (이렇게하면 getArguments ()가 null을 반환합니다).

getSupportFragmentManager().beginTransaction()
    .add(android.R.id.content, frag).commit();

그리고 이것을 조각 코드에 추가하십시오.

@Override
    public void onActivityCreated(Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);

    Bundle bundle = getArguments();
    if(bundle != null)
    {
        listMusics = bundle.getParcelableArrayList("arrayMusic");
        listMusic.setAdapter(new MusicBaseAdapter(getActivity(), listMusics));
    }
}

여기서, listMusics는이다 ArrayListParcelable음악.


첫 번째 단계는 LogCat 창을 열고 예외를 살펴보고 NullPointerException의 원인을 확인하는 것입니다. 알아낼 수 없다면 예외의 스택 추적을 질문에 넣어 누군가가 도울 수 있습니다.
Brian

BrianV : 팁 주셔서 감사합니다! 프로그램을 실행할 때 얻는 LogCat입니다! pastebin.com/ycVcXLFf
다원주의

보기 레이아웃 파일에 오류가있는 것 같습니다. ** 원인 : android.view.InflateException : 바이너리 XML 파일 줄 # 10 : 클래스 조각을 부 풀리는 오류 **
Brian

아니요, 오류는 ListView의 코드에 있습니다. 확실합니다. ListMusicFragment에서 ArrayList of Music 객체를 만들면 코드가 제대로 작동합니다. 어쨌든, 여기 내 레이아웃 파일이 있습니다 : pastebin.com/4DwHh1yk
다원주의

답변:


196

두가지. 먼저 조각에 올바르게 전달하려는 데이터를 추가하고 있다고 생각하지 않습니다. 프래그먼트에 전달해야하는 것은 인 텐트가 아니라 번들입니다. 예를 들어 int조각에 값을 보내고 싶다면 번들을 만들고int 다음 해당 번들을 프래그먼트가 생성 될 때 사용할 인수로 설정합니다.

Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);

두 번째로 해당 정보를 검색하려면 조각으로 전송 된 인수를 가져 오는 데 필요합니다. 그런 다음 식별 한 키를 기반으로 값을 추출합니다. 예를 들어 조각에서 :

Bundle bundle = this.getArguments();
if (bundle != null) {
    int i = bundle.getInt(key, defaulValue);
}

무엇을 넣느냐에 따라 달라집니다. 또한 기본값은 일반적으로null 이지만 반드시 그럴 필요는 없습니다. 해당 인수에 대한 기본값을 설정했는지 여부에 따라 다릅니다.

마지막으로 나는 당신이에서 이것을 할 수 있다고 생각하지 않습니다 onCreateView. 조각의 onActivityCreated메서드 내에서이 데이터를 검색해야한다고 생각합니다 . 내 추론은 다음과 같다. onActivityCreated기본 활동이 자체 onCreate메서드를 완료 한 후에 실행됩니다 . 활동의 onCreate메서드 중에 검색하려는 정보를 번들 내에 배치하는 경우 조각의 onCreateView. 이것을 사용 onActivityCreated하고 ListView나중에 내용을 업데이트하십시오 .


3
간단한 대답, 굉장합니다. 코드 예제를 복사했고 효과가있었습니다!
iamanyone 2013 년

1
그래서 ... 인자가 기본이 아닌 특정 인터페이스를 구현하는 객체에 의해 지정되면 어떻게 될까요?
Piotr

2
객체를 사용하려면 Parcelable인터페이스 를 구현했는지 확인하십시오 . Bundle추가 / 가져 오기를 지원 Parcelable하므로 문제없이 보낼 수 있습니다.
Rarw 2014

1
활동의 layout.xml에 조각이 정의 된 경우에 대한 워크 플로가 있습니까? 이 경우 안드로이드가 조각 자체를 인스턴스화하여 인수를 제공 할 수 없다고 생각합니까? 개인적으로 저는 eventbus (otto)와 생산자를 사용하여 활동에서 조각으로 데이터를 전달합니다.
Alec Holmes

물론입니다. XML에서 조각을 정의 할 때 android : tag 속성을 사용하여 해당 조각에 대한 태그를 설정합니다. 활동에서 FragmentManager.findFragmentByTag ()를 사용하여 해당 조각을 찾은 다음 FragmentTransaction을 사용하여 XML 조각을 원하는 방식으로 구성된 새 조각으로 바꿀 수 있습니다. 또 다른 방법은 findFragmentById를 사용하고 XML 조각의 android : id 값을 사용하는 것입니다.
Rarw 2014-04-13

2

나는 표준 Serializable코드를 선호 하지 않는다. 다른 프래그먼트 또는 활동에 데이터를 전달하는 경우 a와의 속도 차이Parcelable 는 중요하지 않습니다.

또한 항상 Fragment또는에 대한 도우미 메서드를 제공합니다 Activity. 이렇게하면 어떤 데이터를 전달해야하는지 항상 알 수 있습니다. 여기에 대한 예가 있습니다 ListMusicFragment.

private static final String EXTRA_MUSIC_LIST = "music_list";

public static ListMusicFragment createInstance(List<Music> music) {
    ListMusicFragment fragment = new ListMusicFragment();
    Bundle bundle = new Bundle();
    bundle.putSerializable(EXTRA_MUSIC_LIST, music);
    fragment.setArguments(bundle);
    return fragment;
}

@Override
public View onCreateView(...) { 
    ...
    Bundle bundle = intent.getArguments();
    List<Music> musicList = (List<Music>)bundle.getSerializable(EXTRA_MUSIC_LIST);
    ...
}

1

메모리에 중복 데이터가 없기 때문에 번들을 선호하는 이유가 간단합니다. 단편에 대한 init 공개 메소드로 구성됩니다.

private ArrayList<Music> listMusics = new ArrayList<Music>();
private ListView listMusic;


public static ListMusicFragment createInstance(List<Music> music) {
    ListMusicFragment fragment = new ListMusicFragment();
    fragment.init(music);
    return fragment;
}

public void init(List<Music> music){
    this.listMusic = music;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, 
    Bundle savedInstanceState)
{

    View view = inflater.inflate(R.layout.musiclistview, container, false);
    listMusic = (ListView) view.findViewById(R.id.musicListView);
    listMusic.setAdapter(new MusicBaseAdapter(getActivity(), listMusics));

    return view;
}
}

즉, init 메서드 (u는 원하는대로 호출 할 수 있음)로 프래그먼트의 인스턴스를 만듭니다. 직렬화를 통해 프래그먼트의 인스턴스에 대한 복사본을 만들지 않고 목록의 참조를 전달합니다. 목록에서 무언가를 변경하면 앱의 다른 부분에서 얻을 수 있으며 물론 메모리를 적게 사용하기 때문에 이것은 매우 유용합니다.


1
Android에서는 잘못된 방법입니다. 프래그먼트 재 작성 (구성 변경 (화면 회전) 및 기타)시 빈 생성자를 호출하고 모든 매개 변수가 손실되기 때문입니다. newInstancesetArguments권장대로 사용하십시오 .
CoolMind

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.