片段使用来自另一个活动的旧听众

时间:2016-03-15 10:40:38

标签: java android android-fragments onclicklistener android-fragmentactivity

编辑:已解决! 我在我的适配器中使用了static监听器!

我使用的片段显示了两个不同活动中的对象列表:MainActivitySearchActivity(这些活动使用相同的布局activity_base.xml)。

此片段具有OnClikedListener接口,用于管理在RecycleView上单击的项目。监听器设置在片段中的onAttach

问题是:我在MainActivity,我做了一项研究,SearchViewSearchActivity被抛出。 当我通过MainActivity上的后退按钮返回并单击某个项目时,会抛出SearchActivity的监听器。 如果我通过向上按钮返回,它似乎没问题,因为MainActivity被重新创建。

这怎么可能?

很多代码,抱歉:

MainActivity.java

public class MainActivity extends BaseActivity implements MediaListFragment.OnClickedListener {
    private static final String NEWS_FRAGMENT_TAG = "news_fragment_tag";

    @Inject
    MSSEndpoints mssEndpoints;

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

        setContentView(R.layout.activity_base);

        if (savedInstanceState == null && findViewById(R.id.container) != null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container,
                            new MediaListFragmentBuilder(mssEndpoints.newsUrl()).build(),
                            NEWS_FRAGMENT_TAG)
                    .commit();
        }

        getToolbar().setTitle(R.string.news);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        getSearchView().setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                MenuItem searchMenuItem = getSearchMenuItem();
                if (searchMenuItem != null) {
                    searchMenuItem.collapseActionView();
                }
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                return true;
            }
        });
        return true;
    }

    private void loadMedia(Media media) {
        Intent intent = new Intent(MainActivity.this, DetailsActivity.class);
        intent.putExtra(DetailsActivity.MEDIA, media);
        /*
        ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
        MainActivity.this, transitionView, DetailActivity.EXTRA_IMAGE);
        ActivityCompat.startActivity(activity, new Intent(activity, DetailActivity.class),
        options.toBundle());
        */
        startActivity(intent);
    }

    @Override
    public void onItemClicked(Media media) {
        loadMedia(media);
    }
}

SearchActivity.java

public class SearchActivity extends BaseActivity implements MediaListFragment.OnClickedListener {
    private static final String TAG = SearchActivity.class.getSimpleName();

    private static final String MEDIALIST_FRAGMENT_TAG = "medialist_fragment";

    private static final String STATE_SEARCH = "state_search";

    @Inject
    MSSEndpoints mssEndpoints;

    private String search;

    private boolean reload = false;

    MediaListFragment resFragment;

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

        setContentView(R.layout.activity_base);

        if (savedInstanceState != null) {
            search = savedInstanceState.getString(STATE_SEARCH);
        } else if (findViewById(R.id.container) != null) {
            handleIntent(getIntent());
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container,
                            new MediaListFragmentBuilder(mssEndpoints.simpleSearchUrl(search))
                                    .build(),
                            MEDIALIST_FRAGMENT_TAG)
                    .commit();
        }

        ActionBar ab = getSupportActionBar();
        if (ab != null) {
            ab.setDisplayHomeAsUpEnabled(true);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        resFragment = (MediaListFragment) getSupportFragmentManager()
                .findFragmentByTag(MEDIALIST_FRAGMENT_TAG);

        if (reload && search != null) {
            getSearchView().setQuery(search, false);
            // TODO sometimes search is thrown twice
            resFragment.loadPage(mssEndpoints.simpleSearchUrl(search));
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getSearchView().setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                getSearchView().clearFocus();
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                return true;
            }
        });

        // TODO up as home
        getSearchMenuItem().expandActionView();
        getSearchView().setQuery(search, false);
        getSearchView().clearFocus();

        return true;
    }

    @Override
    protected void onNewIntent(Intent intent) {
        handleIntent(intent);
        reload = true;
    }

    @Override
    protected void onSaveInstanceState(Bundle saveInstanceState) {
        super.onSaveInstanceState(saveInstanceState);
        if (search != null) {
            saveInstanceState.putString(STATE_SEARCH, search);
        }
    }

    private void handleIntent(Intent intent) {
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            search = intent.getStringExtra(SearchManager.QUERY);
        }
    }

    @Override
    public void onItemClicked(Media media) {
        Log.d(TAG, "WTF ???????");
    }
}

MedialistFragment.java

@FragmentWithArgs
public class MediaListFragment extends BaseFragment implements MediasAdapter.OnItemClickListener {
    private static final String TAG = MediaListFragment.class.getSimpleName();

    private static final String STATE_MEDIALIST = "state_medialist";

    private static final String STATE_PAGE_LOADED = "page_loaded";

    @Arg
    String page;

    @Inject
    MSSService mssService;

    @Bind(R.id.media_list_recycler_view)
    RecyclerView recyclerView;

    private OnClickedListener listener;

    private boolean isLoading;
    private boolean pageLoaded;

    private MediasAdapter newsAdapter;
    private MediaList mediaList;

    private Observable<MediaList> getMediasObservable;
    private Observer<MediaList> getMediasObserver = new Observer<MediaList>() {
        @Override
        public void onCompleted() {
            getMediasObservable = null;
            isLoading = false;
        }

        @Override
        public void onError(Throwable e) {
            getMediasObservable = null;
            isLoading = false;
        }

        @Override
        public void onNext(MediaList nextList) {
            mediaList.setNextPageUrl(nextList.getNextPageUrl());
            if (newsAdapter != null) {
                newsAdapter.addMedias(nextList.getMedias());
                mediaList.setMedias(newsAdapter.getMedias());
            }

            pageLoaded = true;
        }
    };

    public interface OnClickedListener {
        void onItemClicked(Media media);
    }

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

        if (savedInstanceState != null) {
            mediaList = savedInstanceState.getParcelable(STATE_MEDIALIST);
            pageLoaded = savedInstanceState.getBoolean(STATE_PAGE_LOADED);
        }

        initAdapters();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = LayoutInflater.from(getActivity()).inflate(R.layout.fragment_media_list, container, false);

        ButterKnife.bind(this, rootView);

        recyclerView.setAdapter(newsAdapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        recyclerView.setItemAnimator(new DefaultItemAnimator());

        return rootView;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        try {
            listener = (OnClickedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
            + " must implement OnClickedListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        // To show the problem
        //listener = null;
    }

    @Override
    public void onResume() {
        super.onResume();

        Log.d(getContext().toString(), "LISTENER IS : " + this.listener);
        if (!pageLoaded) {
            loadPage(page);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle saveInstanceState) {
        super.onSaveInstanceState(saveInstanceState);
        if (mediaList != null) {
            saveInstanceState.putParcelable(STATE_MEDIALIST, mediaList);
            saveInstanceState.putBoolean(STATE_PAGE_LOADED, pageLoaded);
        }
    }

    @Subscribe
    public void onMediasLatestPositionEvent(MediasLatestPostionEvent event) {
        if (canPullNextMedias(event.getPosition()))
            pullNextMedias();
    }

    public void setListener(OnClickedListener listener) {
        this.listener = listener;
    }

    public void loadPage(String page) {
        isLoading = true;
        resetAdapters();

        getMediasObservable = mssService
                .getMediaListFromUrl(page)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
        addSubscription(getMediasObservable.subscribe(getMediasObserver));
    }

    private boolean canPullNextMedias(int position) {
        return !isLoading && mediaList != null &&
                !mediaList.getNextPageUrl().equals(DefaultFactory.MediaList.EMPTY_FIELD_NEXT_PAGE_URL) &&
                position > (newsAdapter.getItemCount() - 10);
    }

    private void pullNextMedias() {
        isLoading = true;

        getMediasObservable = mssService
                .getMediaListFromUrl(mediaList.getNextPageUrl())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
        addSubscription(getMediasObservable.subscribe(getMediasObserver));
    }

    private void initAdapters() {
        if (mediaList == null) {
            mediaList = InitialFactory.MediaList.constructInitialInstance();
        }
        newsAdapter = new MediasAdapter(getActivity(), mediaList.getMedias());
        newsAdapter.setOnItemClickListener(this);
    }

    @Override
    public void onItemClick(View itemView, int position) {
        listener.onItemClicked(mediaList.getMedias().get(position));
    }

    private void resetAdapters() {
        mediaList = InitialFactory.MediaList.constructInitialInstance();
        if (newsAdapter != null) {
            newsAdapter.clearMedias();
        }
    }
}

MediaAdapter.java

public class MediasAdapter extends RecyclerView.Adapter<MediasAdapter.ViewHolder> {
    private static final String TAG = MediasAdapter.class.getSimpleName();

    @Inject
    Bus bus;

    private Context context;
    private List<Media> medias;

    private static OnItemClickListener listener;

    public interface OnItemClickListener {
        void onItemClick(View itemView, int position);
    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.listener = listener;
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        @Bind(R.id.title)
        public TextView title;
        @Bind(R.id.author)
        public TextView author;
        @Bind(R.id.icon)
        public ImageView icon;

        public ViewHolder(final View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (listener != null) {
                        listener.onItemClick(itemView, getLayoutPosition());
                    }
                }
            });
        }
    }

    public MediasAdapter(Context context, List<Media> medias) {
        this.context = context;
        this.medias = medias;

        MediasebApp app = MediasebApp.get(context);
        app.inject(this);
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.view_list_item, parent, false));
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        final Media media = medias.get(position);

        bus.post(new MediasLatestPostionEvent(position));

        holder.title.setText(media.getTitle());
        holder.author.setText(media.getAuthor());

        Picasso.with(context).load(media.getImageUrl())
                .into(holder.icon);
    }

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

    public List<Media> getMedias() {
        return medias;
    }

    public void addMedias(List<Media> medias) {
        int currentSize = this.medias.size();
        int amountInserted = medias.size();

        this.medias.addAll(medias);

        notifyItemRangeInserted(currentSize, amountInserted);
    }

    public void clearMedias() {
        int size = medias.size();
        medias.clear();
        notifyItemRangeRemoved(0, size);
    }
}

我尝试在活动中重置onResume上的监听器,在onCreate中设置监听器,使用两种不同的布局,不要搞乱xml ID ......

注意:如果我使用另一个片段进入另一个活动,一切都很好。

感谢您阅读此内容。

0 个答案:

没有答案