shagi
shagi

Reputation: 663

Error: The specified child already has a parent. You must call removeView() on the child's parent first

Can't understand what is wrong, breaking my head for second day...

I want to use TabLayout with 2 tabs, where in first RecyclerView with ArtistModel, but when I inflate Fragment with RecyclerView this error appears.

Here is my code. Fragment

package com.shagi.yandex.lookart.fragment;    

import android.app.Fragment;
import android.os.Bundle;

import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.shagi.yandex.lookart.JsonHelper;
import com.shagi.yandex.lookart.MainActivity;
import com.shagi.yandex.lookart.R;
import com.shagi.yandex.lookart.adaptor.ArtistsAdapter;
import com.shagi.yandex.lookart.pojo.Artist;

import java.util.List;
import java.util.concurrent.ExecutionException;    

/**
 * A simple {@link Fragment} subclass.
 */
public class ArtistsFragment extends Fragment {

    private RecyclerView rvArtists;
    private RecyclerView.LayoutManager layoutManager;

    private ArtistsAdapter adapter;

    private List<Artist> artists;

    public MainActivity activity;

    public ArtistsFragment() {
        // Required empty public constructor
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        if (getActivity() != null) {
            activity = (MainActivity) getActivity();
        }
        loadArtistModels();
    }

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

        View rootView = inflater.inflate(R.layout.fragment_artists, container, false);

        rvArtists = (RecyclerView) rootView.findViewById(R.id.rvArtists);

        layoutManager = new LinearLayoutManager(getActivity());

        rvArtists.setLayoutManager(layoutManager);
        artists = loadArtistModels();

        adapter = new ArtistsAdapter(artists);

        rvArtists.setAdapter(adapter);

        // Inflate the layout for this fragment
        return rootView;
    }

    private List<Artist> loadArtistModels() {
        try {
            return new JsonHelper().execute().get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Adapter

package com.shagi.yandex.lookart.adaptor;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.shagi.yandex.lookart.DownloadImageTask;
import com.shagi.yandex.lookart.R;
import com.shagi.yandex.lookart.pojo.Artist;

import java.util.List;

/**
 * Created by Shagi on 06.04.2016.
 */
public class ArtistsAdapter extends RecyclerView.Adapter<ArtistsAdapter.ViewHolder> {

    List<Artist> artists;

    public ArtistsAdapter(List<Artist> artists) {
        this.artists = artists;
    }

    @Override
    public ArtistsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.model_artist, parent, false);

        ImageView smallCover = (ImageView) v.findViewById(R.id.small_cover);
        TextView name = (TextView) v.findViewById(R.id.tvArtistName);
        TextView style = (TextView) v.findViewById(R.id.tvStyle);
        TextView albums = (TextView) v.findViewById(R.id.tvAlbums);

        return new ViewHolder(parent, smallCover, name, style, albums);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        // - get element from your dataset at this position
        // - replace the contents of the view with that element
        Artist artist = artists.get(position);
        new DownloadImageTask(holder.smallCover).execute(artist.getCover().getSmall());
        holder.artistName.setText(artist.getName());
        String style = "";
        for (String string : artist.getGenres()) {
            style += string + " ";
        }
        holder.artistStyle.setText(style);
        String albums = "альбомов " + artist.getAlbums() + ", треков " + artist.getTracks();
        holder.artistAlbums.setText(albums);
    }

    @Override
    public int getItemCount() {
        return artists.size();
    }    

    public static class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public ImageView smallCover;
        public TextView artistName;
        public TextView artistStyle;
        public TextView artistAlbums;

        public ViewHolder(View v, ImageView img, TextView artistName, TextView artistStyle, TextView artistAlbums) {
            super(v);
            smallCover = img;
            this.artistName = artistName;
            this.artistStyle = artistStyle;
            this.artistAlbums = artistAlbums;
        }
    }
}

And MainActivity

package com.shagi.yandex.lookart;

import android.app.FragmentManager;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;    
import android.view.Menu;
import android.view.MenuItem;    
import com.shagi.yandex.lookart.adaptor.TabAdaptor;
import com.shagi.yandex.lookart.fragment.SplashFragment;

public class MainActivity extends AppCompatActivity {

    FragmentManager fragmentManager;
    PreferenceHelper preferenceHelper;
    TabAdaptor tabAdaptor;

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

        PreferenceHelper.getInstance().init(getApplicationContext());
        preferenceHelper = PreferenceHelper.getInstance();
        fragmentManager = getFragmentManager();


        //runSplash();
        setUI();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        MenuItem splashItem = menu.findItem(R.id.action_splash);
        splashItem.setChecked(preferenceHelper.getBoolean(PreferenceHelper.SPLASH_IS_INVISIBLE));
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_splash) {
            item.setChecked(!item.isChecked());
            preferenceHelper.putBoolean(PreferenceHelper.SPLASH_IS_INVISIBLE, item.isChecked());
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void runSplash() {
        if (!preferenceHelper.getBoolean(PreferenceHelper.SPLASH_IS_INVISIBLE)) {
            SplashFragment splashFragment = new SplashFragment();
            fragmentManager.beginTransaction()
                    .replace(R.id.content_frame, splashFragment).addToBackStack(null).commit();
        }
    }

    public void setUI() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        if (toolbar != null) {
            toolbar.setTitleTextColor(ContextCompat.getColor(getApplicationContext(), R.color.white));
            setSupportActionBar(toolbar);
        }

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        tabLayout.addTab(tabLayout.newTab().setText(R.string.artists_tab));
        tabLayout.addTab(tabLayout.newTab().setText(R.string.selected_artist_tab));

        final ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
        tabAdaptor = new TabAdaptor(fragmentManager, 2);

        viewPager.setAdapter(tabAdaptor);
        viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));

        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                viewPager.setCurrentItem(tab.getPosition());
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });    
    }    
}

stacktrace as asked

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
    at android.view.ViewGroup.addViewInner(ViewGroup.java:4066)
    at android.view.ViewGroup.addView(ViewGroup.java:3916)
    at android.view.ViewGroup.addView(ViewGroup.java:3857)
    at android.support.v7.widget.RecyclerView$5.addView(RecyclerView.java:585)
    at android.support.v7.widget.ChildHelper.addView(ChildHelper.java:107)
    at android.support.v7.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:6249)
    at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:6207)
    at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:6195)
    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1384)
    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1333)
    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:562)
    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2900)
    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3071)
    at android.view.View.layout(View.java:16001)
    at android.view.ViewGroup.layout(ViewGroup.java:5181)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:639)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:574)
    at android.view.View.layout(View.java:16001)
    at android.view.ViewGroup.layout(ViewGroup.java:5181)
    at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1627)
    at android.view.View.layout(View.java:16001)
    at android.view.ViewGroup.layout(ViewGroup.java:5181)
    at android.support.design.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1037)
    at android.support.design.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:747)
    at android.support.design.widget.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:42)
    at android.support.design.widget.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:1133)
    at android.support.design.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:760)
    at android.view.View.layout(View.java:16001)
    at android.view.ViewGroup.layout(ViewGroup.java:5181)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:639)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:574)
    at android.view.View.layout(View.java:16001)
    at android.view.ViewGroup.layout(ViewGroup.java:5181)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:639)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:574)
    at android.view.View.layout(View.java:16001)
    at android.view.ViewGroup.layout(ViewGroup.java:5181)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1959)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1813)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1722)
    at android.view.View.layout(View.java:16001)
    at android.view.ViewGroup.layout(ViewGroup.java:5181)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:639)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:574)
    at android.view.View.layout(View.java:16001)
    at android.view.ViewGroup.layout(ViewGroup.java:5181)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1959)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1813)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1722)
    at android.view.View.layout(View.java:16001)
    at android.view.ViewGroup.layout(ViewGroup.java:5181)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:639)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:574)
    at android.view.View.layout(View.java:16001)
    at android.view.ViewGroup.layout(ViewGroup.java:5181)
    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2467)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2164)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1282)
    at android.

If there is something u couldn't understad, please ask. It seems I can't solve it myself.

Upvotes: 3

Views: 5466

Answers (2)

Ravi Theja
Ravi Theja

Reputation: 3401

You should pass View v instead of parent to your ViewHolder in your onCreateView() method.Also it is better to use initialise Views inside Viewholder rather than in onCreateView()

View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.model_artist, parent, false);

update this line

return new ViewHolder(parent, smallCover, name, style, albums);

to

return new ViewHolder(v, smallCover, name, style, albums);

Upvotes: 5

Raghavendra B
Raghavendra B

Reputation: 441

public class ArtistsFragment extends Fragment {

private ArtistsAdapter adapter;

private List<Artist> artists;

public MainActivity activity;

public ArtistsFragment() {
    // Required empty public constructor
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (getActivity() != null) {
        activity = (MainActivity) getActivity();
    }
    loadArtistModels();
}

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

 RecyclerView rvArtists;
 RecyclerView.LayoutManager
 layoutManager;
    View rootView = inflater.inflate(R.layout.fragment_artists, container, false);

    rvArtists = (RecyclerView) rootView.findViewById(R.id.rvArtists);

    layoutManager = new LinearLayoutManager(getActivity());

    rvArtists.setLayoutManager(layoutManager);
    artists = loadArtistModels();

    adapter = new ArtistsAdapter(artists);

    rvArtists.setAdapter(adapter);

    // Inflate the layout for this fragment
    return rootView;
}

private List<Artist> loadArtistModels() {
    try {
        return new JsonHelper().execute().get();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
    return null;
}

}

If you try to add same child(say TextView object) multiple times to parent then this exception may occur.So to avoid this multiple instances of object should be created then add to your parent.

Upvotes: 0

Related Questions