java.lang.IllegalArgumentException:从给定视图中找不到合适的父级。请提供有效的观点
Posted
技术标签:
【中文标题】java.lang.IllegalArgumentException:从给定视图中找不到合适的父级。请提供有效的观点【英文标题】:java.lang.IllegalArgumentException: No suitable parent found from the given view. Please provide a valid view 【发布时间】:2018-05-19 21:15:01 【问题描述】:我的应用程序在尝试显示服务器消息时崩溃,我认为问题可能出在我的 getView()
上。下面是发生崩溃的registerActivity
和我的activity_register.xml
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.fastchat.helper.SQLiteHandler;
import com.fastchat.helper.SessionManager;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class RegisterActivity extends Activity
private static final String TAG = RegisterActivity.class.getSimpleName();
private Button btnRegister;
private Button btnLinkToLogin;
private EditText inputFullName;
private EditText inputEmail;
private EditText inputPassword;
private ProgressDialog pDialog;
private SessionManager session;
private SQLiteHandler db;
private ProgressBar progress;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
inputFullName = (EditText) findViewById(R.id.name);
inputEmail = (EditText) findViewById(R.id.email);
inputPassword = (EditText) findViewById(R.id.password);
btnRegister = (Button) findViewById(R.id.btnRegister);
btnLinkToLogin = (Button) findViewById(R.id.btnLinkToLoginScreen);
// Progress dialog
pDialog = new ProgressDialog(this);
pDialog.setCancelable(true);
/*
// Session manager
session = new SessionManager(getApplicationContext());
// SQLite database handler
db = new SQLiteHandler(getApplicationContext());
// Check if user is already logged in or not
if (session.isLoggedIn())
// User is already logged in. Take him to main activity
Intent intent = new Intent(RegisterActivity.this,
SearchableActivity.class);
startActivity(intent);
finish();
*/
// Register Button Click event
btnRegister.setOnClickListener(new View.OnClickListener()
public void onClick(View view)
String name = inputFullName.getText().toString();
String email = inputEmail.getText().toString();
String password = inputPassword.getText().toString();
if (!name.isEmpty() && !email.isEmpty() && !password.isEmpty())
registerProcess(name, email, password);
else
Toast.makeText(getApplicationContext(),
"Please enter your details!", Toast.LENGTH_LONG)
.show();
);
// Link to Login Screen
btnLinkToLogin.setOnClickListener(new View.OnClickListener()
public void onClick(View view)
Intent i = new Intent(getApplicationContext(),
LoginActivity.class);
startActivity(i);
finish();
);
private void registerProcess(String name,String email,String password)
String tag_string_req = "req_register";
//pDialog = new AlertDialog.Builder(getActivity());
pDialog.setMessage("please wait");
pDialog.show();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
RequestInterface requestInterface = retrofit.create(RequestInterface.class);
User user = new User();
user.setName(name);
user.setEmail(email);
user.setPassword(password);
ServerRequest request = new ServerRequest();
request.setOperation(Constants.REGISTER_OPERATION);
request.setUser(user);
Call<ServerResponse> response = requestInterface.operation(request);
response.enqueue(new Callback<ServerResponse>()
private View view;
public View getView()
return view;
@Override
public void onResponse(Call<ServerResponse> call, retrofit2.Response<ServerResponse> response)
ServerResponse resp = response.body();
if(resp !=null)//tried to check if resp is null but its not
//crash occurs here
Snackbar.make(getView(),resp.getMessage(), Snackbar.LENGTH_LONG).show();
pDialog.dismiss();
@Override
public void onFailure(Call<ServerResponse> call, Throwable t)
// progress.setVisibility(View.INVISIBLE);
Log.d(Constants.TAG, "failed");
Toast.makeText(getApplicationContext(), t.getLocalizedMessage(), Toast.LENGTH_LONG).show();
pDialog.dismiss();
);
activity_register.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_
android:layout_
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/bg_register"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp"
android:id="@+id/chat">
<LinearLayout
android:layout_
android:layout_
android:layout_gravity="center"
android:orientation="vertical"
android:paddingLeft="20dp"
android:paddingRight="20dp" >
<ImageView
android:layout_
android:layout_
android:layout_gravity="center_horizontal"
android:layout_marginBottom="24dp"
android:src="@drawable/logo"
tools:ignore="ContentDescription" />
<EditText
android:id="@+id/name"
android:layout_
android:layout_
android:layout_marginBottom="10dp"
android:background="@color/input_register_bg"
android:hint="@string/hint_name"
android:padding="10dp"
android:singleLine="true"
android:inputType="textCapWords"
android:textColor="@color/input_register"
android:textColorHint="@color/input_register_hint" />
<EditText
android:id="@+id/email"
android:layout_
android:layout_
android:layout_marginBottom="10dp"
android:background="@color/input_register_bg"
android:hint="@string/hint_email"
android:inputType="textEmailAddress"
android:padding="10dp"
android:singleLine="true"
android:textColor="@color/input_register"
android:textColorHint="@color/input_register_hint" />
<EditText
android:id="@+id/password"
android:layout_
android:layout_
android:layout_marginBottom="10dp"
android:background="@color/input_register_bg"
android:hint="@string/hint_password"
android:inputType="textPassword"
android:padding="10dp"
android:singleLine="true"
android:textColor="@color/input_register"
android:textColorHint="@color/input_register_hint" />
<!-- Login Button -->
<Button
android:id="@+id/btnRegister"
android:layout_
android:layout_
android:layout_marginTop="20dip"
android:background="#ea4c88"
android:text="register"
android:textColor="@color/white" />
<!-- Link to Login Screen -->
<Button
android:id="@+id/btnLinkToLoginScreen"
android:layout_
android:layout_
android:layout_marginTop="40dip"
android:background="@null"
android:text="already a member? login"
android:textAllCaps="false"
android:textColor="@color/white"
android:textSize="15dp" />
</LinearLayout>
下面是logcat消息
java.lang.IllegalArgumentException: No suitable parent found from the given view. Please provide a valid view.
at android.support.design.widget.Snackbar.make(Snackbar.java:137)
at com.chat.RegisterActivity$3.onResponse(RegisterActivity.java:143)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
【问题讨论】:
这里需要一个有效的视图:Snackbar.make(getView(),resp.getMessage(), Snackbar.LENGTH_LONG).show(); ,您可以使用活动中引用的任何视图。 【参考方案1】:我建议你试试findViewById(android.R.id.content)
。
这就是我的诀窍:
Snackbar.make(findViewById(android.R.id.content), resp.getMessage(), Snackbar.LENGTH_LONG).show();
android.R.id.content
将为您提供视图的根元素(有关详细信息,请查看Android: What is android.R.id.content used for?)。
【讨论】:
这是正确的答案@Mani 请接受这个答案,以便其他人可以找到解决方案。 片段呢? @PratikButani 对于片段,您可以使用 getActivity().findViewById(android.R.id.content);并将其包装在一个空检查 if 语句中 if (getActivity() != null) // 显示小吃吧【参考方案2】:我找到了一种解决方案,可以帮助正在寻找通用解决方案的其他人。
我在加载整个 XML 文件之前尝试使用 Snackbar 显示消息时收到此错误。
在片段中,我尝试在onCreateView();
中调用API,并显示Internet connection is off
的Snackbar
消息如下:
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
mBindingObject = DataBindingUtil.inflate(inflater, getLayoutResId(), container, false);
getData();
return mBindingObject.getRoot();
我只是把那个方法放在onViewCreated()
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
getData();
它现在对我有用。
奖励:
在成功加载后总是尝试使用视图。每一个 一行的位置很重要。
谢谢。
【讨论】:
【参考方案3】:用 CoordinatorLayout
包裹你的布局<android.support.design.widget.CoordinatorLayout
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_
android:id="@+id/chat"
android:layout_>
<LinearLayout
android:layout_
android:layout_
android:background="@color/bg_register"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp">
...
...
...
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
【讨论】:
【参考方案4】:我也有这个问题...当然有一点不同...
问题:我使用 MVVM 架构和 LiveData 观察器通过以下代码显示 SnackBar...当我显示另一个片段并再次返回时,我发生了这个错误。
myViewModel.mSnackbar.observe(this, new SnackBarText.SnackbarTextObserver()
@Override
public void onNewMessage(@NotNull YourSnackBarClass msg)
// Showing the message on SnackBar
Snackbar.make(view, msg.getMessage(), Snackbar.LENGTH_LONG).show();
);
解决方案:我在片段暂停时删除了这个观察者(因为我在片段事务中使用了
replace()
)
// fragment area
@Override
protected void onPause()
super.onPause();
mSnackbar.removeObservers(owner)
【讨论】:
【参考方案5】:用这个替换你的视图
getActivity().getCurrentFocus()
.
但不在您的默认片段中
【讨论】:
【参考方案6】:使用 KOTLIN
activity?.window?.decorView?.rootView?.snack("Done !!") fun View.snack(str: String) = Snackbar.make(this, str, Snackbar.LENGTH_SHORT).show()
或者如果你在一个活动中简单地删除activity?.
【讨论】:
【参考方案7】:您正在将 invalid
视图参数传递给 Snackbar。所以你必须给 RegisterActivity BaseLayout 参考。
您应该尝试将 id 声明为 activity_register.xml
Linear / Relative 或您设计的任何内容。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:orientation="vertical"
android:background="#a7b6bdd6"
android:id="@+id/ll1" //here
>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_
android:layout_
android:background="@color/colorPrimary"
android:minHeight="?attr/actionBarSize" />
//your design
</LinearLayout>
然后初始化将此布局传递给如下所示的小吃吧
private void registerProcess(String name,String email,String password)
final LinearLayout linearLayout = (LinearLayout)findViewById(R.id.ll1);// here change
//Snackbar.make(linearLayout,"Hello", Snackbar.LENGTH_LONG).show();
String tag_string_req = "req_register";
//pDialog = new AlertDialog.Builder(getActivity());
pDialog.setMessage("please wait");
pDialog.show();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
RequestInterface requestInterface = retrofit.create(RequestInterface.class);
User user = new User();
user.setName(name);
user.setEmail(email);
user.setPassword(password);
ServerRequest request = new ServerRequest();
request.setOperation(Constants.REGISTER_OPERATION);
request.setUser(user);
Call<ServerResponse> response = requestInterface.operation(request);
response.enqueue(new Callback<ServerResponse>()
private View view;
public View getView()
return view;
@Override
public void onResponse(Call<ServerResponse> call, retrofit2.Response<ServerResponse> response)
ServerResponse resp = response.body();
if(resp !=null)//tried to check if resp is null but its not
//crash occurs here
Snackbar.make(linearLayout,resp.getMessage(), Snackbar.LENGTH_LONG).show();
pDialog.dismiss();
@Override
public void onFailure(Call<ServerResponse> call, Throwable t)
// progress.setVisibility(View.INVISIBLE);
Log.d(Constants.TAG, "failed");
Toast.makeText(getApplicationContext(), t.getLocalizedMessage(), Toast.LENGTH_LONG).show();
pDialog.dismiss();
);
【讨论】:
我试过了,但没有用我还包含了我的register.xml
代码【参考方案8】:
不确定这是否真的那么有用,但是当我尝试使用具有android:fitSystemWindows="true"
和 android:layout_behavior="...BottomSheetBehavior"
的 CoordinatorLayout
视图显示 Snackbar 时,我偶然发现了这个问题,显然你不能在也有行为集的根视图。
我正在做一些重构,然后意识到它没有任何意义,在根视图上设置了一个行为。所以我将CoordinatorLayout
包裹在另一个协调器中,使用新的根视图作为 Snackbar 的视图,一切正常。
【讨论】:
【参考方案9】:如果您在 Show SnackBar
中遇到此错误,您应该在布局中使用 CoordinatorLayout
:
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_
android:id="@+id/coordinator"
android:layout_>
在你的代码中:
val snack = Snackbar.make(
binding.coordinator,
getString(R.string.verification_failed) + e.message,
Snackbar.LENGTH_LONG
)
snack.show()
【讨论】:
【参考方案10】:对我来说,这是因为我在 setContentView(View)
之前初始化了 SnackBar
之前
View v = binding.getRoot();
snackbar = new SnackBarHelper(v); // helper class to init a snackbar
setContentView(v);
然后,在我像这样重新排序代码之后
View v = binding.getRoot();
setContentView(v);
snackbar = new SnackBarHelper(v);
它有效。
【讨论】:
【参考方案11】:发生此错误是因为您尝试获取该片段或活动中不存在的视图。
【讨论】:
【参考方案12】:而不是这个:
Snackbar.make(getView(),resp.getMessage(), Snackbar.LENGTH_LONG).show();
将 getView() 替换为当前活动的现有视图组件,如下所示:
Snackbar.make(findViewById(R.id. chat),resp.getMessage(), Snackbar.LENGTH_LONG).show();
【讨论】:
【参考方案13】:要解决这个异常,你可以这样做。
private void CrearSnackBar(String mensaje)
Snackbar snackbar = Snackbar
.make(constraintLayout, mensaje, Snackbar.LENGTH_LONG)
.setActionTextColor(getResources().getColor(R.color.colorWhite))
.setAction(getResources().getString(R.string.label_settings), new View.OnClickListener()
@Override
public void onClick(View view)
Intent myIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
startActivity(myIntent);
);
View sbView = snackbar.getView();
snackbar.show();
其中constraintLayout是我要显示消息的布局父级,声明布局:
ConstraintLayout 约束布局;
并通过 ID 找到它。
constraintLayout = findViewById(R.id.cl_layout);
该功能对我有用。希望对你有帮助。
【讨论】:
以上是关于java.lang.IllegalArgumentException:从给定视图中找不到合适的父级。请提供有效的观点的主要内容,如果未能解决你的问题,请参考以下文章