【问题标题】:Android passing data between Activities and FragmentsAndroid 在活动和片段之间传递数据
【发布时间】:2020-06-10 19:02:47
【问题描述】:

我的应用程序的基础是 Android 提供的模板“底部菜单导航”

我有一个用户登录活动(使用谷歌),一旦用户登录,我就有意图调用我的 MainActivty。

在我的 MainActivity 中,我执行与 xml 导航(基本上是 3 个片段)一起使用的 AppBarConfiguration。当点击每个底部导航按钮时,会显示一个不同的片段。

Android 使用 ui 包设置 Java 文件夹,其中包含 3 个片段类及其正确的视图模型。

我想要做的是将 google 值(即 givenName 和个人资料图片 URL)从登录名传递到我的第一个片段(仪表板片段),该片段在创建 MainActivity 时加载。

我在登录类中使用了 Bundle,并在 onActivityCreated 的仪表板片段类中使用了 bundle getString。 问题是,当显示我的仪表板时,我的 Bundle 为空。

我假设数据在登录和仪表板片段之间的某处丢失,而 MainActivity 正在创建。

我不认为我必须共享任何编码,我只需要知道如何在活动和片段之间以及可能的视图模型之间正确共享数据?

我的代码:

登录活动

Bundle bundle = new Bundle();
                bundle.putString("GIVEN_NAME",loginItem.getGivenName());
                bundle.putString("PERSON_EMAIL",loginItem.getEmail());
                bundle.putString("PERSON_ID",loginItem.getmID());
                bundle.putString("PERSON_PHOTO",loginItem.getPhotoUri().toString());
                DashboardFragment fragment = new DashboardFragment();
                fragment.setArguments(bundle);

仪表板片段

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

    //Get login intent
    Bundle bundle = this.getArguments();
    if (bundle != null) {
        personGivenName = bundle.getString("GIVEN_NAME","No Name");
        personEmail = bundle.getString("PERSON_EMAIL","No Email");
        personID = bundle.getString("PERSON_ID","NA");
        personPhoto = Uri.parse(bundle.getString("PERSON_PHOTO",""));
    }//if
}//onActivityCreated

任何帮助将不胜感激。

++++++++++++++++++++++++编辑++++++++++++++++++++++ 创建了一个新的类 Singleton(命名为你喜欢的 wtv)

public class SingletonUserInfo {
private String uID;
private String username;
private String uEmail;
private Uri uProfilePic;

//Singleton object
private static SingletonUserInfo INSTANCE = null;

// other instance variables can be here
private SingletonUserInfo() { };

public static SingletonUserInfo getInstance() {
    if (INSTANCE == null) {
        INSTANCE = new SingletonUserInfo();
    }//if
    return(INSTANCE);
}//getInstance

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

public String getuID() {
    return uID;
}

public void setuID(String uID) {
    this.uID = uID;
}

public String getuEmail() {
    return uEmail;
}

public void setuEmail(String uEmail) {
    this.uEmail = uEmail;
}

public Uri getuProfilePic() {
    return uProfilePic;
}

public void setuProfilePic(Uri uProfilePic) {
    this.uProfilePic = uProfilePic;
}

}//类

然后以这种方式从单例中传递和获取值:

SingletonUserInfo.getInstance().setuEmail(personEmail);
SingletonUserInfo.getInstance().getuEmail();

编码愉快!

【问题讨论】:

  • 您是否尝试过使用意图?如果您对使用 Google 进行干净的 Firebase 身份验证感兴趣,可以查看此article
  • 您说 DashboardFragment 是“在创建 [...] MainActivity 时加载的”。由于您不太可能将 DashboardFragment 的实例从 LoginActivity 传递到 MainActivity,因此您似乎首先在 LoginActivity 中使用正确的参数 Bundle 创建了一个 DashboardFragment 实例,但实际上您并没有对它做任何事情。接下来,为了在 MainActivity 中显示 Fragment,您在 MainActivity 中创建另一个 DashboardFragment 实例,而不设置任何参数并显示它。到目前为止我猜对了吗?
  • @BömachtBlau 是的,这就是我认为正在发生的事情..
  • 那么你应该首先将Bundle从LoginActivity传递给MainActivity。如果您需要帮助,请分享更多代码,然后我们将能够建议一种尽可能接近您现有代码的方法
  • 如果您有时间并准备好学习新知识,那就更好了 :-) 以防万一您需要另一个链接来帮助您:guide to app architecture 是我的起点。话虽如此,由于 Bundles 仍然可以在导航图中发挥作用,因此知道如何使用它们并没有什么坏处。从您在第一种方法中遇到的问题中,请记住始终将参数 Bundle 分配给 Fragment 的某个实例。它不是 Java 意义上的静态(如“设置一次,到处检索”)。

标签: android firebase google-signin


【解决方案1】:

如果您需要访问相同的数据,则不应通过捆绑包传递它们。使用捆绑包传递数据可能会减慢您的应用程序(Parcing 数据会降低性能)。 相反,您可以尝试组合使用 Singleton 和 ViewModel。 例如。

class LoginViewModel(
    private val userController : Controller
): ViewModel() {
    fun login(){
        userController.downloadUsers()
    }
    //some code...
    fun getUser(name: String): User{
        return userController.findUser(name)
    }
}
class DetailsScreenViewModel(
    private val userController : Controller
): ViewModel() {
    //some code...
    fun getUser(name: String): User{
        return userController.findUser(name)
    }
}

/**
 * Singleton class
 */
class Controller(){
    private var users = mutableListOf<User>()

    /**
     * Download users from a server.
     */
    fun downloadUsers(){
        users.add(User("Super User"))
        users.add(User("Good User"))
    }

    /**
     * Find a user.
     */
    fun findUser(name: String): User{
        return users.find { it.name == name } ?: throw NoUserFound()
    }
}
class NoUserFound(): Exception()

data class User(var name: String)

【讨论】:

  • 首先我强烈推荐 Kotlin 而不是 Java。你知道单例是什么吗?你知道什么是依赖注入以及如何使用它吗?
  • 做了一些研究,发现您的解决方案效果最好!虽然,您的解决方案对我的应用程序来说有点复杂,但您仍然为我指明了正确的方向!谢谢!在我的帖子中发布我的解决方案
  • 如果你想“增强”你的代码,你应该使用干净的架构检查 mvvm。你可以从this开始。
【解决方案2】:

在活动中创建包,并将其作为参数分配给片段。

Bundle mbundle = new Bundle();
bundle.putString("key", "value");
Fragmentclass mfrag = new Fragmentclass();
mfrag.setArguments(mbundle);

然后您在片段中的 onCreateView 中检索它。

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    String value = getArguments().getString("key");    
    return inflater.inflate(R.layout.fragment, container, false);
}

我希望这会有所帮助!

【讨论】:

  • 我确实这样做了,我仍然得到一个空值。
【解决方案3】:

尝试使用静态字段或接口。

在您的 Activity 类中,

 HashMap<T> pojoMap =new HashMap<>();

private void setYourPojo(){
//Add your data to HashMap
 }

 public static HashMap<T> getYourPojo(){
 return pojoMap;}

并从您的 Fragment onCreateView 调用它

 HashMap<T> getYourData = Activity.getYourPojo();

注意:但是如果你使用异步任务,你应该使用Interface而不是静态HashMap。否则你的 HashMap 数据将为空。

【讨论】:

    猜你喜欢
    • 2016-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-27
    • 2014-04-03
    相关资源
    最近更新 更多