【问题标题】:java.lang.IllegalArgumentException: No suitable parent found from the given view. Please provide a valid viewjava.lang.IllegalArgumentException:从给定视图中找不到合适的父级。请提供有效的观点
【发布时间】: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_width="fill_parent"
android:layout_height="fill_parent"
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_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical"
    android:paddingLeft="20dp"
    android:paddingRight="20dp" >

    <ImageView
        android:layout_width="389dp"
        android:layout_height="72dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="24dp"
        android:src="@drawable/logo"
        tools:ignore="ContentDescription" />


    <EditText
        android:id="@+id/name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        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_width="fill_parent"
        android:layout_height="wrap_content"
        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_width="fill_parent"
        android:layout_height="wrap_content"
        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_width="fill_parent"
        android:layout_height="wrap_content"
        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_width="fill_parent"
        android:layout_height="wrap_content"
        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(); ,您可以使用活动中引用的任何视图。

标签: java android web server


【解决方案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_width="match_parent"
         android:id="@+id/chat"
         android:layout_height="match_parent">
         <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              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_width="match_parent"
                          android:layout_height="match_parent"
                          android:orientation="vertical"
                          android:background="#a7b6bdd6"
                android:id="@+id/ll1"  //here 
                 >
            
                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="64dp"
                    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_width="match_parent"
                  android:id="@+id/coordinator"
                  android:layout_height="match_parent">
              

              在你的代码中:

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

                      该功能对我有用。希望对你有帮助。

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2021-08-24
                        • 2018-12-14
                        • 2019-05-21
                        • 2020-01-15
                        • 2016-11-09
                        • 1970-01-01
                        • 2020-11-16
                        • 2016-01-26
                        相关资源
                        最近更新 更多