单击其他片段中的搜索按钮时应用程序崩溃
App crashes when I click the search button in my other fragments
我的天气应用程序通过在其搜索面板上搜索城市来工作,而且效果很好。唯一的问题是,如果我单击底部导航视图中的下一个选项卡(每小时和每天部分),然后
单击那里的搜索按钮,它显示以下异常:
java.lang.ClassCastException: com.viz.lightweatherforecast.SecondFragment cannot be cast to com.viz.lightweatherforecast.FirstFragment
at com.viz.lightweatherforecast.Activity.HomeActivity.onClick(HomeActivity.java:94)
at android.view.View.performClick(View.java:7044)
at android.view.View.performClickInternal(View.java:7017)
at android.view.View.access00(View.java:784)
at android.view.View$PerformClick.run(View.java:26596)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6819)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:497)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:912)
这个错误清楚地表明错误来自 activity 上的这一行:
FirstFragment firstFragment = (FirstFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
firstFragment.getWeatherData(textfield.getText().toString().trim());
所以我尝试添加这个:
SecondFragment secondFragment = (SecondFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
secondFragment.getWeatherData(textfield.getText().toString().trim());
所以它可以支持我的secondfragment,但它仍然报错。我也在这个网站上搜索了答案,但没有找到任何解决方案。
为了进一步解释该应用程序,我有一个 activity 托管 3 个片段(Firstfragment、Secondfragment 和 Thirdfragment。第一个标记为今天,第二个标记为每小时,第三个标记为每日天气。
我暂时不打算使用每小时和每天的标签,直到应用程序的更高版本。
我的其他片段目前是空的(上面没有写代码),我现在只想坚持使用今天选项卡。
但是修复这个错误是必要的,以防用户点击它。
我的目的只是确保如果我单击其他选项卡上的搜索按钮不会出现此类错误,请帮助。
我的Activity代码:
public class HomeActivity extends AppCompatActivity {
// Last update time, click sound, search button, search panel.
TextView time_field;
MediaPlayer player;
ImageView Search;
EditText textfield;
// For scheduling background image change(using constraint layout, start counting from dubai, down to statue of liberty.
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);
// use home activity layout.
time_field = findViewById(R.id.textView9);
Search = findViewById(R.id.imageView4);
textfield = findViewById(R.id.textfield);
// find the id's of specific variables.
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
// host 3 fragments along with bottom navigation.
final NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
assert navHostFragment != null;
final NavController navController = navHostFragment.getNavController();
NavigationUI.setupWithNavController(bottomNavigationView, navController);
// For scheduling background image change
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.dubai);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// run on ui thread
runOnUiThread(() -> {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
});
}
}, 5000, 5000);
Search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// make click sound when search button is clicked.
player = MediaPlayer.create(HomeActivity.this, R.raw.click);
player.start();
getWeatherData(textfield.getText().toString().trim());
// make use of some fragment's data
FirstFragment firstFragment = (FirstFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
firstFragment.getWeatherData(textfield.getText().toString().trim());
}
private void getWeatherData(String name) {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<Example> call = apiInterface.getWeatherData(name);
call.enqueue(new Callback<Example>() {
@Override
public void onResponse(@NonNull Call<Example> call, @NonNull Response<Example> response) {
try {
assert response.body() != null;
time_field.setVisibility(View.VISIBLE);
time_field.setText("Last Updated:" + " " + response.body().getDt());
} catch (Exception e) {
time_field.setVisibility(View.GONE);
time_field.setText("Last Updated: Unknown");
Log.e("TAG", "No City found");
Toast.makeText(HomeActivity.this, "No City found", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
t.printStackTrace();
}
});
}
});
}
}
Activity.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout"
android:background="@drawable/dubai"
tools:context=".Activity.HomeActivity">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFFFFF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_menu" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="409dp"
android:layout_height="599dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:navGraph="@navigation/my_nav"
/>
<EditText
android:id="@+id/textfield"
android:layout_width="250dp"
android:layout_height="35dp"
android:autofillHints="@string/change_city"
android:background="@color/colorPrimary"
android:hint="@string/search_city"
android:inputType="text"
android:labelFor="@id/imageView4"
android:padding="8dp"
android:textColor="@color/colorAccent"
android:textSize="16sp"
app:layout_constraintEnd_toStartOf="@+id/imageView4"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView4"
android:layout_width="50dp"
android:layout_height="35dp"
android:layout_marginEnd="1dp"
android:contentDescription="@string/searchbtn"
android:src="@drawable/look"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/time_field"
android:visibility="gone"
android:textColor="#FFFFFF"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textfield" />
</androidx.constraintlayout.widget.ConstraintLayout>
要从 NavHostFragment 获得对显示片段的正确引用,您必须先检查片段 Class 在尝试向下转型之前先键入。
根据您的问题:
App crashes when I click the search button in my other fragments
在其他片段之间切换时,您无法始终将 FirstFragment 或 SecondFragment 实例检索为可见片段。
所以只需将您的代码更改为如下所示:
Fragment currentFragment = (Fragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
if(currentFragment instanceof FirstFragment) {
FirstFragment firstFragment = (FirstFragment)currentFragment;
firstFragment.getWeatherData(textfield.getText().toString().trim());
}
else if(currentFragment instanceof SecondFragment) {
SecondFragment secondFragment = (SecondFragment)currentFragment;
secondFragment.getWeatherData(textfield.getText().toString().trim());
}
else if(currentFragment instanceof ThirdFragment) {
ThirdFragment thirdFragment = (ThirdFragment)currentFragment;
thirdFragment.getWeatherData(textfield.getText().toString().trim());
}
我的天气应用程序通过在其搜索面板上搜索城市来工作,而且效果很好。唯一的问题是,如果我单击底部导航视图中的下一个选项卡(每小时和每天部分),然后 单击那里的搜索按钮,它显示以下异常:
java.lang.ClassCastException: com.viz.lightweatherforecast.SecondFragment cannot be cast to com.viz.lightweatherforecast.FirstFragment
at com.viz.lightweatherforecast.Activity.HomeActivity.onClick(HomeActivity.java:94)
at android.view.View.performClick(View.java:7044)
at android.view.View.performClickInternal(View.java:7017)
at android.view.View.access00(View.java:784)
at android.view.View$PerformClick.run(View.java:26596)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6819)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:497)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:912)
这个错误清楚地表明错误来自 activity 上的这一行:
FirstFragment firstFragment = (FirstFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
firstFragment.getWeatherData(textfield.getText().toString().trim());
所以我尝试添加这个:
SecondFragment secondFragment = (SecondFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
secondFragment.getWeatherData(textfield.getText().toString().trim());
所以它可以支持我的secondfragment,但它仍然报错。我也在这个网站上搜索了答案,但没有找到任何解决方案。
为了进一步解释该应用程序,我有一个 activity 托管 3 个片段(Firstfragment、Secondfragment 和 Thirdfragment。第一个标记为今天,第二个标记为每小时,第三个标记为每日天气。
我暂时不打算使用每小时和每天的标签,直到应用程序的更高版本。 我的其他片段目前是空的(上面没有写代码),我现在只想坚持使用今天选项卡。 但是修复这个错误是必要的,以防用户点击它。
我的目的只是确保如果我单击其他选项卡上的搜索按钮不会出现此类错误,请帮助。
我的Activity代码:
public class HomeActivity extends AppCompatActivity {
// Last update time, click sound, search button, search panel.
TextView time_field;
MediaPlayer player;
ImageView Search;
EditText textfield;
// For scheduling background image change(using constraint layout, start counting from dubai, down to statue of liberty.
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);
// use home activity layout.
time_field = findViewById(R.id.textView9);
Search = findViewById(R.id.imageView4);
textfield = findViewById(R.id.textfield);
// find the id's of specific variables.
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
// host 3 fragments along with bottom navigation.
final NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
assert navHostFragment != null;
final NavController navController = navHostFragment.getNavController();
NavigationUI.setupWithNavController(bottomNavigationView, navController);
// For scheduling background image change
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.dubai);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// run on ui thread
runOnUiThread(() -> {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
});
}
}, 5000, 5000);
Search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// make click sound when search button is clicked.
player = MediaPlayer.create(HomeActivity.this, R.raw.click);
player.start();
getWeatherData(textfield.getText().toString().trim());
// make use of some fragment's data
FirstFragment firstFragment = (FirstFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
firstFragment.getWeatherData(textfield.getText().toString().trim());
}
private void getWeatherData(String name) {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<Example> call = apiInterface.getWeatherData(name);
call.enqueue(new Callback<Example>() {
@Override
public void onResponse(@NonNull Call<Example> call, @NonNull Response<Example> response) {
try {
assert response.body() != null;
time_field.setVisibility(View.VISIBLE);
time_field.setText("Last Updated:" + " " + response.body().getDt());
} catch (Exception e) {
time_field.setVisibility(View.GONE);
time_field.setText("Last Updated: Unknown");
Log.e("TAG", "No City found");
Toast.makeText(HomeActivity.this, "No City found", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
t.printStackTrace();
}
});
}
});
}
}
Activity.xml代码:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/layout"
android:background="@drawable/dubai"
tools:context=".Activity.HomeActivity">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottomNavigationView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FFFFFF"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="@menu/bottom_menu" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="409dp"
android:layout_height="599dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:navGraph="@navigation/my_nav"
/>
<EditText
android:id="@+id/textfield"
android:layout_width="250dp"
android:layout_height="35dp"
android:autofillHints="@string/change_city"
android:background="@color/colorPrimary"
android:hint="@string/search_city"
android:inputType="text"
android:labelFor="@id/imageView4"
android:padding="8dp"
android:textColor="@color/colorAccent"
android:textSize="16sp"
app:layout_constraintEnd_toStartOf="@+id/imageView4"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView4"
android:layout_width="50dp"
android:layout_height="35dp"
android:layout_marginEnd="1dp"
android:contentDescription="@string/searchbtn"
android:src="@drawable/look"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/time_field"
android:visibility="gone"
android:textColor="#FFFFFF"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textfield" />
</androidx.constraintlayout.widget.ConstraintLayout>
要从 NavHostFragment 获得对显示片段的正确引用,您必须先检查片段 Class 在尝试向下转型之前先键入。
根据您的问题:
App crashes when I click the search button in my other fragments
在其他片段之间切换时,您无法始终将 FirstFragment 或 SecondFragment 实例检索为可见片段。
所以只需将您的代码更改为如下所示:
Fragment currentFragment = (Fragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
if(currentFragment instanceof FirstFragment) {
FirstFragment firstFragment = (FirstFragment)currentFragment;
firstFragment.getWeatherData(textfield.getText().toString().trim());
}
else if(currentFragment instanceof SecondFragment) {
SecondFragment secondFragment = (SecondFragment)currentFragment;
secondFragment.getWeatherData(textfield.getText().toString().trim());
}
else if(currentFragment instanceof ThirdFragment) {
ThirdFragment thirdFragment = (ThirdFragment)currentFragment;
thirdFragment.getWeatherData(textfield.getText().toString().trim());
}