按钮单击更新recyclerview
我的Android应用程序中有另一个问题或错误。对不起,我是Android开发新手,但这是我的激情,我会坚持下去。按钮单击更新recyclerview
无论如何,我的代码在我的CustomAdapter类的方法调用中崩溃。
这是我CustomAdapter类在那里崩溃:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder> {
private ArrayList<UserInfo> arrayList = new ArrayList<UserInfo>();
float ratings;
public CustomAdapter(ArrayList<UserInfo> arrayList){
this.arrayList = arrayList;
}
@Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.userslayout, parent, false);
CustomViewHolder customViewHolder = new CustomViewHolder(view);
return customViewHolder;
}
@Override
public void onBindViewHolder(final RecyclerViewHolder holder, int position) {
final UserInfo userInfo = arrayList.get(position);
holder.username.setText(userInfo.getMusicName());
holder.forename.setText(userInfo.getMusicCategory());
holder.surname.setText(userInfo.getFileType());
// THE APP CRASHES WHEN I CLICK THIS BUTTON. THINGS UPDATE IN THE
// DATABASE - BUT THE RECYCLERVIEW CRASHES AND THE APP CRASHES
holder.buttonRefresh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String pressed = Integer.toString(userInfo.getPressedName());
UserListRecycler userListRecycler = new UserListRecycler();
UserListRecycler.UserPressedAsync userPressedAsync = userListRecycler.new UserPressedAsync();
userPressedAsync.execute(username, pressed);
}
});
}
}
这是我UserListRecycler
类 - 主类和内部类UserPressedAsync
public class UserListRecycler extends Fragment {
RecyclerView recyclerView;
static UserAdapter adapter;
RecyclerView.LayoutManager layoutManager;
ArrayList<UserInfo> list;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.userlistGUI, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.reUsers);
recyclerView.setHasFixedSize(true);
list = new ArrayList<UserInfo>();
// Instantiate new adapter here
adapter = new MusicRecyclerAdapter(list);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(linearLayoutManager);
// Sets the adapter here
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
return rootView;
}
@Override
public void onStart() {
super.onStart();
populateRecyclerList();
}
public void populateList(){
PopulateUsers userList = new PopulateUsers(list, adapter, recyclerView);
userList.execute();
}
public class UserPressedAsync extends AsyncTask<String, String, String> {
@Override
protected String doInBackground(String... params) {
// REST STUFF HAPPENS HERE
}
@Override
protected void onPostExecute(String postData) {
// CRASHES HERE!!!
populateRecyclerList();
}
}
}
这是我的PopulateUsers
班 - 我的服务器的详细信息通过REST
public class PopulateUsers extends AsyncTask<String, String, String> {
static ArrayList<UserInfo> list;
UserAdapter adapter;
RecyclerView recyclerView;
public PopulateUsers(ArrayList<UserInfo> list, UserAdapter adapter, RecyclerView recyclerView) {
this.list = new ArrayList<UserInfo>();
this.adapter = new UserAdapter();
this.list = list;
this.adapter = adapter;
this.recyclerView = recyclerView;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
// `REST` Activity happens here
}
@Override
protected void onPostExecute(String s) {
try {
list.clear();
JSONArray jsonArray = new JSONArray(s);
for (int i = 0; i < jsonArray.length(); i++) {
String forename = jsonArray.getJSONObject(i).getString("forename");
String surname = jsonArray.getJSONObject(i).getString("surname");
String nationality = jsonArray.getJSONObject(i).getString("nationality");
UserInfo userInfo = new UserInfo(forename, surname, nationality);
list.add(userInfo);
}
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
基本上,单击该按钮时,事情正在朝着backend
更新,即phpmyadmin
mysql
服务器 - 但它崩溃的应用程序不与更新的列表刷新。这与UserListRecycler
类中的populateList()
方法有关,它指向PopulateUsers
类中的recyclerView.setAdapter(adapter);
错误 - 正好在中,错误类型为NullPointerException
,但它在UserListRecycler
类首次实例化并加载时工作正常。那么为什么它会崩溃,当我打电话给populateList()
方法?
这是我的堆栈跟踪:
java.lang.NullPointerException
at lukasz.usersapp.PopulateUsers.onPostExecute(PopulateUsers.java:67)
at lukasz.usersapp.PopulateUsers.onPostExecute(PopulateUsers.java:27)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5103)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:525)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
at dalvik.system.NativeStart.main(Native Method)
这将真正意味着很多,其实有些睡眠自己,如果有人可以帮助我解决这个问题。这是一个可怕的错误!
该错误基本上来自您正在访问您的recyclerview而其适配器尚未实例化的事实。这是因为您在主线程中显示recyclerview,同时在后台进行设置。在你的情况下,两个线程不同步,所以当你点击按钮时,recyclerview还没有正确设置,因此给你一个空指针异常。
我建议你找到解决办法,让数据显示出来,然后在显示之前设置你的回收站。
使用asynctask进行网络调用真的不是一个好主意,你通常必须使用像retrofit,gson,rxandroid等库,但是因为你刚刚开始,你必须用asynctask做。
我建议你做你的recyclerView.setAdapter(adapter)
在你的主线程就像在你onCreate
,因为你没有显示你的recyclerview所需的数据,你必须要么使用虚拟数据首次设置或者,更优选,唐不显示它,先显示一个进度条,告诉用户它还没有完成加载。
如果您按照我的建议进行操作,则无需在您的asynctask中致电recyclerView.setAdapter(adapter)
,您只需通知它您已进行更改,这当然是您的adapter.notifyDataSetChanged()
。
recyclerView.setAdapter(adapter);
您拨打的两倍。为什么不把它放在onCreateView
中,并将其从postExecute
中删除?只需将adapter.notifyDataSetChanged()
保留在postExecute中,并将其从onCreateView中删除即可。这有什么不同吗?
我正在使用库Volley这些任务,它的使用相当简单。看起来也比ASyncTask
好看。也许你可以试试看。
看一看那个页面:http://developer.android.com/training/volley/index.html
如果克隆Volley library
(文件夹会下载),通过New>Import MODULE>path to library
其导入到Android的工作室。然后,你需要把compile project(':volley')
到您应用的Build gradle
下的依赖 - 所以它看起来是这样的:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:23.1.1'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.android.support:design:23.1.1'
compile project(':volley')
}
这是我的方法,从我的PHP服务下载JSON
的样子:
public void downloadEvents(String urlService) {
RequestQueue requestQueue = Volley.newRequestQueue(getActivity()); //getActivity because I'm calling it from a fragment, if called in Activity, use 'this'
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest
(Request.Method.GET, urlService, null, new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
try {
for (int i = 0; i < response.length(); i++) {
JSONObject eventJson = response.getJSONObject(i);
String title = eventJson.getString("EventTitle");
String body = eventJson.getString("EventBody");
double price = Double.parseDouble(eventJson.getString("EventPrice"));
String date = eventJson.getString("EventDate");
String time = eventJson.getString("EventTime");
String place = eventJson.getString("EventPlace");
String organ = eventJson.getString("Organization");
Event event = new Event(title, body, price, date, time, durationStr, place, organ);
theEvents.add(event);
rAdapter.notifyItemInserted(i);
}
if (swipeRefreshLayout.isRefreshing()) {
swipeRefreshLayout.setRefreshing(false);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY ERROR", "" + error);
}
}
);
requestQueue.add(jsonArrayRequest); //important to add that otherwise the download wont be initiated.
}
你可以看到我如何处理我的JSON,以及在哪里可以使用像swipeRefreshLayout
这样的东西。 请注意,这仍然是asynchronously
。
重要的是去检查您的JSON responses
并查看响应是以对象还是数组开头。然后相应地调整Volley
代码。它基本上将代码中的大多数Array
关键字更改为Object
(如果您正在接收包含您的数据的JSON对象)。例如:
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest
(Request.Method.GET, urlService, null, new Response.Listener<JSONArray>() {
成为
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, urlService, null, new Response.Listener<JSONObject>() {
....
在我的onCreate,使用downloadEvents("http//example.com/service.php");
我已经做了所有的RecyclerView
和适配器代码之前:
recyclerView = (RecyclerView) fragmentView.findViewById(R.id.rv);
LinearLayoutManager llm = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(llm);
theEvents = new ArrayList<>();
rAdapter = new RecyclerAdapter(theEvents, recyclerView);
recyclerView.setAdapter(rAdapter);
下载方法只是通知适配器。
如何使用volley,is there任何方式我可以将我的代码转换为凌空? –
我给你几乎完整的Volley教程。我希望它很简单,它可以帮助你。我这样做的方式(现在)这个方法是我设置数据的地方,所以我的列表和适配器在同一个类(片段)中。这就是为什么我只是添加到列表并通知我的适配器。 – iBobb
谢谢,但是什么是事件事件=新事件(标题,正文,价格,日期,时间,durationStr,地点,器官);'?另外,如果我要将抽签代码放在一个单独的类中,它会起作用吗? –
那么我该如何解决这个可怕的错误?我实际上无法入睡,并且一直将我的头撞在墙上 –
有没有办法可以修复我的代码?当然,它正在移动一条线 –
你的json从哪里来?从api? – hehe