在Retrofit中的Enqueue方法未在Fragment中加载数据。

huangapple 未分类评论56阅读模式
标题翻译

Enqueue method in Retrofit doesn't load data in Fragment

问题

过去的3天中,我一直遇到问题,无法使用 Retrofit 2.4.0 在 Fragment 中的 RecyclerView 中加载数据。我可以在终端中看到数据从服务器使用相对 URL 获取,但无法填充数据(当我调试代码时,OnResponse 和 OnFailure 被跳过)。此外,我在应用程序界面上看到一些垃圾值。有一些关于这方面的问题已经有答案,但没有一个解决方案适用于我。尽管我已经在 GitHub 上进行了研究,但没有找到任何解决方案。迄今为止,我有以下代码。

以下是 Retrofit 的实例:

以下是 Fragment 类:

RecyclerAdapter 如下所示:

build.gradle(Module:app):

在这方面提供的任何帮助将不胜感激。提前谢谢。

英文翻译

I have been struck from the past 3 days and unable to load data on recyclerview in Fragment using retrofit 2.4.0.I can see in terminal that the data is being fetched from the server using realtive url but couldn't populate it(means OnReponse and OnFailure is skipped when i debug the code).Furthermore, I can see some garbage values on the application UI. There are some questions that have answered in this regard but none of the solution works for me.Even though I have researched on the github but haven't found any solution there. Uptill now, I have following code.

public interface UserAPIEndPoint {
    @GET("posts")
    Call<List<Post>> getAllUsers();
}

Following is the Retrofit Instance

public class RetrofitInstance {
    public static Retrofit retrofit;
    private static final String base_Url = "https://jsonplaceholder.typicode.com/";
    public static Retrofit getRetrofitInstance(){
        if (retrofit == null){
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();

            retrofit = new Retrofit.Builder()
                    .baseUrl(base_Url)
                    .client(client)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }
        return retrofit;
    }
}

Here is the Fragment class

public class MessageFragment extends Fragment {
    private RecyclerView recyclerView;
    private List<Post> user;
    private PostAdapter userAdapter;
    private LinearLayoutManager layoutManager;
    View rootView;
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_message,container,false);
        loadJSON();
        return rootView;
    }

    private void loadJSON() {
        try {
        UserAPIEndPoint userAPIEndPoint= RetrofitInstance.getRetrofitInstance().create(UserAPIEndPoint.class);
        Call<List<Post>> userlist = userAPIEndPoint.getAllUsers();
//        userlist.execute();
    userlist.enqueue(new Callback<List<Post>>() {
            @Override
            public void onResponse(Call<List<Post>> call, Response<List<Post>> response) {
                user = response.body();
                recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview);
                recyclerView.setHasFixedSize(true);
                layoutManager = new LinearLayoutManager(getActivity());
                recyclerView.setLayoutManager(layoutManager);
                recyclerView.setItemAnimator(new DefaultItemAnimator());
                userAdapter = new PostAdapter(getActivity(),user);
                recyclerView.setAdapter(userAdapter);

            }

            @Override
            public void onFailure(Call<List<Post>> call, Throwable t) {

            }
        });
        } catch (Exception e) {
            Log.d("Error", e.getMessage());
            Toast.makeText(getActivity(), e.toString(), Toast.LENGTH_SHORT).show();
        }
    }
}

Post.class is converted through pojo2schema.
RecyclerAdapter is as follow.

public class PostAdapter extends RecyclerView.Adapter<PostAdapter.ViewHolder> {
    private List<Post> posts;
    private Context mcontext;

    public PostAdapter(Context context,List<Post> post){
        this.posts = post;
        this.mcontext =context;
    }

    @NonNull
    @Override
    public PostAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout_post,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.userid.setText(String.valueOf(posts.get(position).getUserId()));
        holder.id.setText(String.valueOf(posts.get(position).getId()));
        holder.title.setText(posts.get(position).getTitle());
        holder.body.setText(posts.get(position).getBody());
    }


    @Override
    public int getItemCount() {
        return posts.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        private TextView userid,id,title,body;

        public ViewHolder(View itemView) {
            super(itemView);
            userid = (TextView) itemView.findViewById(R.id.userId);
            id = (TextView) itemView.findViewById(R.id.id);
            title = (TextView) itemView.findViewById(R.id.title);
            body = (TextView) itemView.findViewById(R.id.body);

        }
    }

}

build.gradle(Module:app)

apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.scratchnavigation"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "androidx.core:core:1.4.0-alpha01"
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.google.android.material:material:1.1.0-alpha04'
    implementation 'com.google.firebase:firebase-core:16.0.3'
    implementation 'com.google.firebase:firebase-auth:16.0.3'
    implementation 'com.miguelcatalan:materialsearchview:1.4.0'

    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    testImplementation 'junit:junit:4.13'

    implementation 'com.google.code.gson:gson:2.8.5'
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
    implementation 'de.hdodenhof:circleimageview:3.1.0'
    implementation "androidx.cardview:cardview:1.0.0"
    implementation 'com.github.bumptech.glide:glide:4.11.0'
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation "androidx.drawerlayout:drawerlayout:1.0.0"
    implementation "androidx.cardview:cardview:1.0.0"
    implementation 'com.squareup.okhttp3:logging-interceptor:4.7.2'
    implementation 'com.squareup.okhttp3:okhttp:4.7.2'
    implementation 'org.conscrypt:conscrypt-android:2.4.0'
}

Any help in this regard is highly appreciated. Thanks in advance.

答案1

得分: 0

以下是您要翻译的内容:

我相信这是因为它是一个异步网络调用。您是在不同的线程中创建一切。

有两种方法可以解决这个问题。

1.) 尝试创建一个处理程序(Handler)以在主线程上发布数据集已更改的消息,类似于:

Handler mHandler = new Handler(Looper.getMainLooper());
mHandler.post(new Runnable() {
    @Override
    public void run() {
        userAdapter = new PostAdapter(user);
        recyclerView.setAdapter(userAdapter);
        if (userAdapter != null) {
            userAdapter.notifyDataSetChanged(userAdapter);
            recyclerView.setVerticalScrollbarPosition(userAdapter.getItemCount());
        }
        recyclerView.smoothScrollToPosition(userAdapter.getItemCount());
    }
});

2.) 在 onCreateView 方法中为 recyclerViewAdapter 赋值,使其如下所示:

public class MessageFragment extends Fragment {
    private RecyclerView recyclerView;
    private List<Post> user;
    private PostAdapter userAdapter;
    private LinearLayoutManager layoutManager;
    View rootView;

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_message, container, false);

        recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview);
        recyclerView.setHasFixedSize(true);
        layoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        userAdapter = new PostAdapter(getActivity(), null);
        recyclerView.setAdapter(userAdapter);

        loadJSON();
        return rootView;
    }

    private void loadJSON() {
        // ... (您提供的 loadJSON() 方法内容)
    }
}

然后您还可以为 PostsAdapter 类更改 setData 方法:

public class PostAdapter extends RecyclerView.Adapter<PostAdapter.ViewHolder> {
    // ... (您提供的 PostsAdapter 类内容)

    public void setData(@NonNull List<Post> list) {
        if (list.size() > 0) {
            posts = list;
        }
        this.notifyDataSetChanged();
    }

    // ... (您提供的 ViewHolder 内容)
}
英文翻译

I believe this is because it is an async network call. Your creating everything in a different thread.

There are 2 ways to solve this.

1.) Try creating a handler to post on the main thread that the dataset has changed something like

        Handler mHandler = new Handler(Looper.getMainLooper());
    mHandler.post(new Runnable() {
        @Override
        public void run() {
            userAdapter = new PostAdapter(user);
            recyclerView.setAdapter(userAdapter);
            if (userAdapter != null) {
                userAdapter.notifyDataSetChanged(userAdapter);
                recyclerView.setVerticalScrollbarPosition(userAdapter.getItemCount());
            }
            recyclerView.smoothScrollToPosition(userAdapter.getItemCount());
        }
    });
}

2.) In the onCreateView assign the recyclerView and Adapter So it looks like:

    public class MessageFragment extends Fragment {
    private RecyclerView recyclerView;
    private List&lt;Post&gt; user;
    private PostAdapter userAdapter;
    private LinearLayoutManager layoutManager;
    View rootView;
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.fragment_message,container,false);
        
        recyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerview);
        recyclerView.setHasFixedSize(true);
        layoutManager = new LinearLayoutManager(getActivity());
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        userAdapter = new PostAdapter(getActivity(), null);
        recyclerView.setAdapter(userAdapter);
        
        loadJSON();
        return rootView;
    }

    private void loadJSON() {
        try {
            UserAPIEndPoint userAPIEndPoint= RetrofitInstance.getRetrofitInstance().create(UserAPIEndPoint.class);
            Call&lt;List&lt;Post&gt;&gt; userlist = userAPIEndPoint.getAllUsers();
            userlist.enqueue(new Callback&lt;List&lt;Post&gt;&gt;() {
                @Override
                public void onResponse(Call&lt;List&lt;Post&gt;&gt; call, Response&lt;List&lt;Post&gt;&gt; response) {
                    user = response.body();
                    userAdapter.setData(user);
                }

                @Override
                public void onFailure(Call&lt;List&lt;Post&gt;&gt; call, Throwable t) {

                }
            });
        } catch (Exception e) {
            Log.d(&quot;Error&quot;, e.getMessage());
            Toast.makeText(getActivity(), e.toString(), Toast.LENGTH_SHORT).show();
        }
    }
}

Which you can then also amend the PostsAdapter for that method

    public class PostAdapter extends RecyclerView.Adapter&lt;PostAdapter.ViewHolder&gt; {
    private List&lt;Post&gt; posts;
    private Context mcontext;

    public PostAdapter(Context context,List&lt;Post&gt; post){
        this.posts = post;
        this.mcontext =context;
    }

    @NonNull
    @Override
    public PostAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_layout_post,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
        holder.userid.setText(String.valueOf(posts.get(position).getUserId()));
        holder.id.setText(String.valueOf(posts.get(position).getId()));
        holder.title.setText(posts.get(position).getTitle());
        holder.body.setText(posts.get(position).getBody());
    }


    @Override
    public int getItemCount() {
        return posts.size();
    }
    
    public void setData(@NonNull List&lt;Posts&gt; list){
        if(list.size() &gt; 0) {
            posts = list;
        }
        this.noftifyDataSetChanged();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        private TextView userid,id,title,body;

        public ViewHolder(View itemView) {
            super(itemView);
            userid = (TextView) itemView.findViewById(R.id.userId);
            id = (TextView) itemView.findViewById(R.id.id);
            title = (TextView) itemView.findViewById(R.id.title);
            body = (TextView) itemView.findViewById(R.id.body);

        }
    }

}

huangapple
  • 本文由 发表于 2020年5月30日 23:43:53
  • 转载请务必保留本文链接:https://java.coder-hub.com/62104860.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定