Android 在 Activity 和 Fragment 之间传递数据

Android passing data between Activities and Fragments

我的应用程序的基础是 Android 提供的模板 "bottom menu navigation"

我有一个 activity 用于用户登录(使用 google),一旦用户登录,我打算调用我的 MainActivty。

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

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

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

我在登录 class 中使用了 Bundle,并在 onActivityCreated 的仪表板片段 class 中使用了 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);

DashboardFragment

@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

如有任何帮助,我们将不胜感激。

++++++++++++++++++++++ 编辑++++++++++++++++++++ 创建了一个新的 class 单例(将其命名为你喜欢的 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;
}

}//class

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

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

编码愉快!

从 activity 中创建包,并将其作为参数分配给片段。

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);
}

希望对您有所帮助!

如果您需要访问相同的数据,则不应通过捆绑包传递它们。使用捆绑包传递数据可能会降低您的应用程序速度(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)

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

在你的Activityclass,

 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();

注意:但是如果你使用Asynchronous任务,你应该使用Interface而不是static HashMap。否则你的 HashMap 数据将是空的。

Kotlin 解决方案在这里。我想拥有多项活动的通用数据。我创建了一个新的 Base activity class 开始是这样的...

open class BaseActivity : AppCompatActivity() {
companion object {
    lateinit var basePref: SharedPreferences
    lateinit var basePrefEdit: SharedPreferences.Editor
    private var initFlag = 0
    ...
}

然后我让所有 activity class 来自 BaseActivity 而不是 AppCompatActivity。伴随对象 {...} 是您在 Kotlin 中粘贴东西的地方,您希望所有实例都通用一个版本。在这种情况下,我有一组偏好读取对象,以及一个我们将在设置后设置的标志。