通过FragmentStateAdapter将数据从Activity传递到Fragment。

huangapple go评论72阅读模式
英文:

Pass data from Activity to Fragment via FragmentStateAdapter

问题

我目前正在为一个记分助手应用程序开发一个个人项目应用。目标是使用该应用程序跟踪每个玩家的分数,并具有高分和其他其他功能。

当前,我有一个使用ViewPager2的选项卡式活动(Tabbed Activity)。对于熟悉它的人,你会比我知道得多,但我注意到我从未在活动中实例化Fragment类,只在FragmentStateAdapter中实例化。在我的活动中,我只使用两个选项卡,一个用于游戏方面,一个用于分数显示。考虑到这一点,我的活动类看起来像这样:

EightHoleActivity.java

// 代码...

正如你所看到的,我有一个RoomDatabase,我用它来存储应用程序中的数据。当我通过意图启动这个活动时,我传递正在进行的游戏的ID。这就是我遇到问题的地方。

我想要做的:

我想将我从intent.getLongExtra("GameID", 0)中获得的变量gameID传递到EightHoleScoresFragment类。

我尝试使用BundleputParcelableArrayList(),但没有成功。

这是我使用的其他类。注意,Participants.java 类是我想提取的,其中包括gameID变量。

Participants.java

// 代码...

EightHolePagerAdapter.java

// 代码...

EightHoleScoresFragment.java

// 代码...

对于理解正在发生的情况,我为代码的数量感到抱歉。我认为所有这些代码都是必要的。我尝试过使用Bundle,如我所说,遵循站点上的各种答案,但都没有成功。我不确定是否有可能直接将意图的内容直接传递给EightHoleScoresFragment,并通过链接返回到父级EightHoleActivity的方法,但我不确定...

提前谢谢!

英文:

I am currently working on a personal project application for a scoring helper app. The aim is to use the app to keep track of points for each player and have high scores and other fancy features.

Right now, I have a Tabbed Activity which uses ViewPager2. For those familiar with it, you'll know a lot more than I do but what I've noticed is that I never instantiate my Fragment classes in the activity, only in the FragmentStateAdapter. In my activity, I only use two tabs, one for the game aspect and one for the points display. With this in mind, my activity class looks like this:

EightHoleActivity.java

package com.example.game;

import android.content.Intent;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;

public class EightHoleActivity extends AppCompatActivity {

    private long gameID;
    private RoomDB database;

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

        Intent intent = getIntent();
        gameID = intent.getLongExtra("GameID", 0);
        database = RoomDB.getInstance(EightHoleActivity.this);

        ViewPager2 viewPager2 = findViewById(R.id.eight_hole_view_pager);
        viewPager2.setAdapter(new EightHolePagerAdapter(this));
        TabLayout tabLayout = findViewById(R.id.eight_hole_tabs);
        TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(
                tabLayout, viewPager2, (tab, position) -> {
                    switch (position){
                        case 0: {
                            tab.setText("Current game");
                            tab.setIcon(R.drawable.ic_twotone_games_24);
                            break;
                        }
                        default: {
                            tab.setText("Scores");
                            tab.setIcon(R.drawable.ic_baseline_list_24);
                            break;
                        }
                    }
                }
        );
        tabLayoutMediator.attach();
    }
}

As you can see, I have a RoomDatabase which I use to store the data within the application. When I start this activity by intent, I pass the ID of the game that is being played. This is where I am having issue.

What I want to do:

I want to pass the variable gameID that I get from intent.getLongExtra("GameID", 0) all the way down to the EightHoleScoresFragment class.

I've had no luck with the use of Bundle and putParcelableArrayList()

Here are the other classes that I use.
Note that the class Participants.java is what I want to extract with the gameID variable.

Participants.java

package com.example.game;

import android.os.Parcel;
import android.os.Parcelable;

import androidx.annotation.Nullable;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.PrimaryKey;

import java.util.Objects;

@Entity(tableName = "participants", foreignKeys = {
        @ForeignKey(entity = Player.class, parentColumns = "id", childColumns = "player_id", onDelete = ForeignKey.CASCADE),
        @ForeignKey(entity = Game.class, parentColumns = "id", childColumns = "game_id", onDelete = ForeignKey.CASCADE)})
public class Participant implements Parcelable {
    @PrimaryKey(autoGenerate = true)
    private long id;

    @ColumnInfo(name = "player_id", index = true)
    private long playerID;

    @ColumnInfo(name = "game_id", index = true)
    private long gameID;

    @ColumnInfo(name = "score")
    private int score;

    protected Participant(Parcel in) {
        id = in.readLong();
        playerID = in.readLong();
        gameID = in.readLong();
        score = in.readInt();
    }

    public static final Creator<Participant> CREATOR = new Creator<Participant>() {
        @Override
        public Participant createFromParcel(Parcel in) {
            return new Participant(in);
        }

        @Override
        public Participant[] newArray(int size) {
            return new Participant[size];
        }
    };

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public long getPlayerID() {
        return playerID;
    }

    public void setPlayerID(long playerID) {
        this.playerID = playerID;
    }

    public long getGameID() {
        return gameID;
    }

    public void setGameID(long gameID) {
        this.gameID = gameID;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public Participant(long playerID, long gameID){
        this.playerID = playerID;
        this.gameID = gameID;
    }

    @Override
    public boolean equals(@Nullable Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof Participant)) return false;

        Participant participant = (Participant) obj;
        if (id != participant.id) return false;
        return Objects.equals(score, participant.score) || Objects.equals(playerID, participant.playerID) || Objects.equals(gameID, participant.gameID);
    }

    @Override
    public int hashCode() {
        int result = (int) id;
        result = (int) (31 * result + playerID + gameID + score);
        return result;
    }

    @Override
    public String toString() {
        return "Participant{" +
                "ID=" + id +
                ", PlayerID='" + playerID + '\'' +
                ", GameID='" + gameID + '\'' +
                ", Score='" + score + '\'' +
                '}';
    }

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeLong(id);
        dest.writeLong(playerID);
        dest.writeLong(gameID);
        dest.writeInt(score);
    }
}

EightHolePagerAdapter.java

package com.example.game;

import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;

public class EightHolePagerAdapter extends FragmentStateAdapter {

    public EightHolePagerAdapter(@NonNull FragmentActivity fragmentActivity) {
        super(fragmentActivity);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        switch (position){
            case 0:
                return new EightHoleGameFragment();
            default:
                return new EightHoleScoresFragment();
        }
    }

    @Override
    public int getItemCount() {
        return 2;
    }
}

EightHoleScoresFragment.java

package com.example.game;

import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import java.util.ArrayList;

public class EightHoleScoresFragment extends Fragment {

    private ArrayList<Participant> participants = new ArrayList<Participant>();

    public EightHoleScoresFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_eight_hole_scores, container, false);
        ListView listView = (ListView) view.findViewById(R.id.eight_hole_current_scores_list);

        ScoresAdapter adapter = new ScoresAdapter(getActivity(), R.layout.scores_adapter_layout, participants);
        listView.setAdapter(adapter);
        return view;
    }
}

I apologize for the digest amount of code. I feel it's all necessary to be able to understand what is going on. I've tried to use Bundle as I said, following various answers on the site but none have worked. I wonder if it would be at all possible to directly pass the contents of the intent to the EightHoleScoresFragment with a method that links back to the parents EightHoleActivity but I'm not sure...

Thanks in advance!

答案1

得分: 3

请尝试以下方法:

在Activity中:

将gameId作为额外的参数传递,并在Adapter中接收。

viewPager2.setAdapter(new EightHolePagerAdapter(this, gameID));

在ViewPagerAdapter中:

EightHoleScoresFragment 接受gameId并调用fragment的newInstance方法。

public class EightHolePagerAdapter extends FragmentStateAdapter {

    private long gameId;

    public EightHolePagerAdapter(@NonNull FragmentActivity fragmentActivity, long gameId) {
        super(fragmentActivity);
        this.gameId = gameId;
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        switch (position){
            case 0:
                return new EightHoleGameFragment();
            default:
                return EightHoleScoresFragment.newInstance(gameId);
        }
    }

    @Override
    public int getItemCount() {
        return 2;
    }
}

在你的Fragment中:

以这种方式接收gameId参数。

public class EightHoleScoresFragment extends Fragment {

    private static final String ARG_GAME_ID = "game_id";
    private long mGameId;

    public static EightHoleScoresFragment newInstance(long gameId) {
        EightHoleScoresFragment fragment = new EightHoleScoresFragment();
        Bundle args = new Bundle();
        args.putLong(ARG_GAME_ID, gameId);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mGameId = getArguments().getLong(ARG_GAME_ID);
        }
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Log.d("EightHoleScoresFragment", "Game Id = " + mGameId);
    }
}
英文:

Please try this approach

In Activity:

Pass gameId as extra argument and receive in Adapter

viewPager2.setAdapter(new EightHolePagerAdapter(this, gameID));

In ViewPagerAdapter:

EightHoleScoresFragment takes gameId and calls fragment newInstance

public class EightHolePagerAdapter extends FragmentStateAdapter {

    private long gameId;

    public EightHolePagerAdapter(@NonNull FragmentActivity fragmentActivity, long gameId) {
        super(fragmentActivity);
        this.gameId = gameId;
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        switch (position){
            case 0:
                return new EightHoleGameFragment();
            default:
                return EightHoleScoresFragment.newInstance(gameId);
        }
    }

    @Override
    public int getItemCount() {
        return 2;
    }
}

In your Fragment :

Receive gameId arguments in fragment this way.

public class EightHoleScoresFragment extends Fragment {

    private static final String ARG_GAME_ID = "game_id";
    private long mGameId;

    public static EightHoleScoresFragment newInstance(long gameId) {
        EightHoleScoresFragment fragment = new EightHoleScoresFragment();
        Bundle args = new Bundle();
        args.putLong(ARG_GAME_ID, gameId);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mGameId = getArguments().getLong(ARG_GAME_ID);
        }
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        Log.d("EightHoleScoresFragment", "Game Id = " + mGameId);
    }
}

huangapple
  • 本文由 发表于 2020年9月22日 03:41:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/63998971.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定