当前位置: 首页 > 知识库问答 >
问题:

如何让我的碎片利用我的活动数据?

裘臻
2023-03-14

我有一个托管3个片段的活动,我的活动包含一些我希望我的第一个片段使用的数据。我尝试调用以下方法,以便活动可以与片段通信:

FirstFragment fragmentFirst = (FirstFragment)
                getSupportFragmentManager().findFragmentById(R.id.firstFragment);
        assert fragmentFirst != null;
        fragmentFirst.doSomething("some param");

对于活动类和:

public void doSomething(String param) {
        // do something in fragment
    }

对于fragment类,但它在运行时对空对象引用错误调用虚拟方法“void com.tex.lightweatherforecast.FirstFragment.doSomething(java.lang.String)”。

我的活动代码是:

public class HomeActivity extends AppCompatActivity {
    public static String BaseUrl = "http://api.openweathermap.org/";
    public static String AppId = "9c547bfc852923c3b30d0d62a5ae35e8";
    public static String lat = "9.0574";
    public static String lon = "7.4898";
    // User Timezone name, current time, current temperature, current condition, sunrise, sunset, temperature, pressure, humidity, wind_speed, visibility, UV Index
    TextView time_zone, time_field, current_temp, current_output, rise_time, set_time, temp_out, Press_out, Humid_out, Ws_out, Visi_out, UV_out;
    ConstraintLayout constraintLayout;
    public static int count=0;
    int[] drawable =new int[]{R.drawable.dubai,R.drawable.central_bank_of_nigeria,R.drawable.eiffel_tower,R.drawable.hong_kong,R.drawable.statue_of_liberty};
    Timer _t;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        FirstFragment fragmentFirst = (FirstFragment)
                getSupportFragmentManager().findFragmentById(R.id.firstFragment);
        assert fragmentFirst != null;
        fragmentFirst.doSomething("some param");

        time_zone = findViewById(R.id.textView9);
        time_field = findViewById(R.id.textView4);
        current_temp = findViewById(R.id.textView10);
        current_output = findViewById(R.id.textView11);
        rise_time = findViewById(R.id.textView25);
        set_time = findViewById(R.id.textView26);
        temp_out = findViewById(R.id.textView28);
        Press_out = findViewById(R.id.textView29);
        Humid_out = findViewById(R.id.textView30);
        Ws_out = findViewById(R.id.textView33);
        Visi_out = findViewById(R.id.textView34);
        UV_out = findViewById(R.id.textView35);

        BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
        NavController navController = Navigation.findNavController(this, R.id.fragment);
        NavigationUI.setupWithNavController(bottomNavigationView, navController);

        findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getCurrentData();
                constraintLayout = findViewById(R.id.layout);
        constraintLayout.setBackgroundResource(R.drawable.dubai);
        _t = new Timer();
        _t.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() { // run on ui thread
                    @Override
                    public void run() {
                        if (count < drawable.length) {

                            constraintLayout.setBackgroundResource(drawable[count]);
                            count = (count + 1) % drawable.length;
                        }
                    }
                });
            }
        }, 5000, 5000);
    }

            void getCurrentData() {
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BaseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    WeatherService service = retrofit.create(WeatherService.class);
    Call<WeatherResponse> call = service.getCurrentWeatherData(lat, lon, AppId);
        call.enqueue(new Callback<WeatherResponse>() {
            @Override
            public void onResponse(@NonNull Call<WeatherResponse> call, @NonNull Response<WeatherResponse> response) {
                if (response.code() == 200) {
                    WeatherResponse weatherResponse = response.body();
                    assert weatherResponse != null;

                    assert response.body() != null;
                    time_zone.setText(response.body().getTimezone());
                    time_field.setText(response.body().getCurrent().getDt());
                    current_temp.setText(response.body().getCurrent().getTemp() + " ℃");
                    current_output.setText(response.body().getCurrent().getWeather().get(0).getDescription());
                    rise_time.setText(response.body().getCurrent().getSunrise() + " AM");
                    set_time.setText(response.body().getCurrent().getSunset() + " PM");
                    temp_out.setText(response.body().getCurrent().getTemp() + " ℃");
                    Press_out.setText(response.body().getCurrent().getPressure() + " hpa");
                    Humid_out.setText(response.body().getCurrent().getHumidity() + " %");
                    Ws_out.setText(response.body().getCurrent().getWindSpeed() + " Km/h");
                    Visi_out.setText(response.body().getCurrent().getVisibility() + " m");

                }
            }

            @Override
            public void onFailure(@NonNull Call<WeatherResponse> call, @NonNull Throwable t) {
            }
        });
            }
        });
    }
}

任何帮助将不胜感激

共有2个答案

呼延卓
2023-03-14

如果您想在第一个目标片段中传递活动数据,请避免在活动布局文件中设置图形。

从活动布局中删除图形实现。并在活动的on创建方法中如下所示地实现它。

    NavController navController = Navigation.findNavController(this, R.id.nav_controller);
    Bundle bundle = new Bundle();
    bundle.putString("key", "value");
    navController.setGraph(navController.getGraph(), bundle);

通过参考以下代码更新图形文件。

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/navigation_graph"
        app:startDestination="@id/homeFragment">

    <fragment android:id="@+id/homeFragment"
          android:name="com.java.HomeFragment"
          android:label="home_fragment"
          tools:layout="@layout/fragment_home">

            <argument 
                android:name="key"
                app:argType="string"/>

    </fragment>

    ...
    ...

</navigation>

在主片段中,获取参数值。

 String data = getArguments().getString("key");
秋建义
2023-03-14

我想你得到这个错误是因为这个片段没有被激活。如果它是活动的,并且这种方法有效,这是一种非常糟糕的方法,当我们使用新的LiveData和ViewModel arch风格时,还有其他方法。

如果您认为子级(片段)需要DataSource(通常为LiveData),请将此DataSource归父级(活动)所有,并在片段内监视该DataSource

如果您需要从Fragment回调到活动,请使用Contracts(Interfaces)并在活动中实现该契约(该契约可能包含doSomething()等函数),然后从片段中调用该契约,如下所示:

(((ContractName)activity).doSomething(passData))
 类似资料:
  • 我一直对此感到沮丧,也找不到好的答案,所以希望这里有人能提供指导。 我有一个片段相当广泛地使用了。片段调用(返回null)时,我经常受到错误的困扰。我假设发生这些情况是因为在附加活动之前或分离活动之后调用了片段中的某些方法。 在我的代码中处理这个问题的正确方法是什么?我不想让这个成语到处乱扔, 一些人建议在暂停时取消任务,但这意味着标准习惯用语, 无法使用。这意味着每个执行的都需要跟踪到完成或取消

  • 我有很多活动。 A是列表活动。 B是表单活动。并动态生成。我连续开了两次这个活动。 我怎样才能像碎片一样管理活动。 *当我从第二个B返回时,第一个B应该打开*

  • 我有一个大型Android游戏,其中每个逻辑屏幕都有一个活动。(启动画面、开始画面、关卡选择器、游戏画面和设置是不同的活动)。现在一切正常。 如果我重写所有内容,使得只有一个活动,逻辑屏幕是碎片,会减少RAM或CPU消耗吗?

  • 我可以使用一个片段作为一个活动吗?我已经创建了一个片段,但我希望它有像活动一样的功能,所以我使用片段扩展碎片活动。然而,我有一个带有碎片的导航抽屉。当我更改为“扩展碎片活动”时,我的代码有问题?请给我指路。

  • 由于不推荐使用TabActivity,我需要找到一种方法来使用片段。在我知道它如何工作之前,我已经使用了碎片,但我需要一个指南来创建我的标签主机与碎片活动。我在互联网上找到了几个例子,它们都是关于将片段放入标签的容器中的。

  • 我一直对此感到沮丧,我找不到一个好的答案,所以希望这里有人能提供指导。 我有一个片段非常广泛地使用了。我经常被bug困扰,其中片段调用,返回null。我假设发生这些情况是因为在附加活动之前或分离活动之后调用了片段中的某些方法。 在我的代码中处理这个问题的正确方法是什么?我不想把这个成语到处乱扔, 查看