I've tried to look for a solution but I have not been able to find one with my specific situation. I'm using a recyclerview with GSON and I'm getting the message of skipping layout. My code looks correct but I know I should set an empty adapter in the onCreateView section. I'm not sure how to exactly do that. Any help will be appreciated. My fragment activity is below.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_weather_app, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addItemDecoration(new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL));
new GetWeatherAync().execute(getActivity());
return view;
}
private class GetWeatherAync extends AsyncTask<Context, Void,
List<ForecastWeatherList>> {
private String TAG = GetWeatherAync.class.getSimpleName();
private Context mContext;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected List<ForecastWeatherList> doInBackground(Context...params) {
mContext = params[0];
return getWeatherFromServer();
}
#Override
protected void onPostExecute(List<ForecastWeatherList> result) {
super.onPostExecute(result);
if (result != null) {
Log.e(TAG, "populate UI recycler view with gson converted data");
RecyclerViewAdapter weatherRecyclerViewAdapter = new RecyclerViewAdapter(result, mContext);
mRecyclerView.setAdapter(weatherRecyclerViewAdapter);
}
}
}
public List<ForecastWeatherList> getWeatherFromServer(){
String serviceUrl = "http://api.openweathermap.org/data/2.5/forecast?q=" + searchView + api_key;
URL url = null;
try {
url = new URL(serviceUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setConnectTimeout(4000);
connection.setReadTimeout(4000);
connection.connect();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
//pass buffered reader to convert json to javaobject using gson
return convertJsonToObject(bufferedReader);
}catch (Exception e){
}
return null;
}
public List<ForecastWeatherList> convertJsonToObject(BufferedReader bufferedReader){
final Gson gson = new Gson();
//pass root element type to fromJson method along with input stream
ForecastWeatherListWrapper weatherWrapper = gson.fromJson(bufferedReader,ForecastWeatherListWrapper.class);
List<ForecastWeatherList> weatherlst = weatherWrapper.getforecastWeatherLists();
return weatherlst;
}
EDIT:
So I've implemented the following changes:
Listener Interface.
import com.ksburneytwo.weathertest.ForecastWeather.ForecastWeatherList;
import java.util.List;
public interface Listener {
void afterSearch(List<ForecastWeatherList> result);
}
Fragment:
public static WeatherAppFragment newInstance(String param1, String param2) {
WeatherAppFragment fragment = new WeatherAppFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_weather_app, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addItemDecoration(new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL));
new GetWeatherAync().execute(getActivity());
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu, menu);
MenuItem searchItem = menu.findItem(R.id.menu_search);
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) {
searchView = (SearchView) searchItem.getActionView();
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
queryTextListener = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) {
Log.i("onQueryTextChange", newText);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
Log.i("onQueryTextSubmit", query);
return true;
}
};
searchView.setOnQueryTextListener(queryTextListener);
}
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public void afterSearch(List<ForecastWeatherList> result) {
mRecyclerView.setAdapter(new RecyclerViewAdapter(result, mRecyclerView.getContext()));
}
private static class GetWeatherAync extends AsyncTask<Context, Void, List<ForecastWeatherList>> {
private String TAG = GetWeatherAync.class.getSimpleName();
private final String serviceUrl;
private Context mContext;
private Listener listener;
GetWeatherAync(Listener listener,String searchView, String api_key) {
this.listener = listener;
this.serviceUrl = "http://api.openweathermap.org/data/2.5/forecast?q=" + searchView + api_key;
}
#Override
protected List<ForecastWeatherList> doInBackground(Context...params) {
try {
URL url = new URL(serviceUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setConnectTimeout(4000);
connection.setReadTimeout(4000);
connection.connect();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
ForecastWeatherListWrapper weatherWrapper = new Gson().fromJson(bufferedReader, ForecastWeatherListWrapper.class);
return weatherWrapper.getforecastWeatherLists();
} catch (Exception e) {}
return null;
}
#Override
protected void onPostExecute(List<ForecastWeatherList> result) {
super.onPostExecute(result);
if (result != null) {
Log.e(TAG, "populate UI recycler view with gson converted data");
listener.afterSearch(result);
}
}
}
Here is the recyclerview adapter.
public class RecyclerViewAdapter extends
RecyclerView.Adapter<RecyclerViewAdapter.ForecastRecycler> {
List<ForecastWeatherList> mForecastWeatherDataList;
public static class ForecastRecycler extends RecyclerView.ViewHolder{
public TextView currentTemp;
public TextView currentHumidity;
public TextView currentDescription;
public ImageView currentIcon;
public ForecastRecycler (View view) {
super (view);
currentTemp = (TextView) view.findViewById(R.id.current_temperature);
currentHumidity = (TextView) view.findViewById(R.id.current_humidity);
currentDescription = (TextView) view.findViewById(R.id.current_weather_description);
currentIcon = (ImageView) view.findViewById(R.id.current_weather_icon);
}
}
public RecyclerViewAdapter(List<ForecastWeatherList> mForecastWeatherDataList, Context mContext) {
this.mForecastWeatherDataList = mForecastWeatherDataList;
}
#Override
public ForecastRecycler onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
final ForecastRecycler currentRecycler = new ForecastRecycler(view);
return currentRecycler;
}
#Override
public void onBindViewHolder( ForecastRecycler holder, int position) {
final ForecastWeatherList currentRecycler = mForecastWeatherDataList.get(position);
holder.currentTemp.setText((currentRecycler.getMain().getTempKf()));
holder.currentHumidity.setText(currentRecycler.getMain().getHumidity());
holder.currentDescription.setText(currentRecycler.getWeather().getDescription());
Picasso.with(holder.currentIcon.getContext()).load(currentRecycler.getWeather().getIcon());
}
#Override
public int getItemCount() {
return mForecastWeatherDataList.size();
}
}
Here are my current logs. I know its connecting to the server but I'm still getting no adapter attached error.
11371-11371/com.ksburneytwo.weathertest D/debugMode: The application is in onCreateView
11371-11396/com.ksburneytwo.weathertest D/debugMode: The application is in doInBackground
11371-11371/com.ksburneytwo.weathertest E/RecyclerView: No adapter attached; skipping layout
11371-11396/com.ksburneytwo.weathertest D/NetworkSecurityConfig: No Network Security Config specified, using platform default
11371-11396/com.ksburneytwo.weathertest D/debugMode: The application stopped after catch
Try notifyDataSetChanged() in adapter after initializing in onCreateView() method.
or use this approach:
Listener:
public interface Listener {
void afterSearch(List<ForecastWeatherList> result);
}
Fragment:
public class MyFragment extends Fragment implements Listener {
RecyclerView mRecyclerView;
List<ForecastWeatherList> items = new ArrayList<>();
RecyclerViewAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_weather_app, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addItemDecoration(new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL));
adapter = new RecyclerViewAdapter(items, mRecyclerView.getContext());
mRecyclerView.setAdapter(adapter);
new GetWeatherAync(this, searchView, api_key).execute();
return view;
}
public afterSearch(List<ForecastWeatherList> result) {
items = result;
adapter.notifyDataSetChanged();
}
}
AsyncTask:
private static class GetWeatherAync extends AsyncTask<Context, Void, List<ForecastWeatherList>> {
private String TAG = GetWeatherAync.class.getSimpleName();
private final String serviceUrl;
private Context mContext;
private Listener listener;
public GetWeatherAync(Listener listener, Object searchView, Object api_key) {
this.listener = listener;
this.serviceUrl = "http://api.openweathermap.org/data/2.5/forecast?q=" + searchView + api_key;
}
#Override
protected List<ForecastWeatherList> doInBackground(Context...params) {
try {
URL url = new URL(serviceUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setConnectTimeout(4000);
connection.setReadTimeout(4000);
connection.connect();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
ForecastWeatherListWrapper weatherWrapper = new Gson().fromJson(bufferedReader, ForecastWeatherListWrapper.class);
return weatherWrapper.getforecastWeatherLists();
} catch (Exception e) {}
return null;
}
#Override
protected void onPostExecute(List<ForecastWeatherList> result) {
super.onPostExecute(result);
if (result != null) {
Log.e(TAG, "populate UI recycler view with gson converted data");
listener.afterSearch(result);
}
}
}
Related
I'm trying to work on a weather app and I have tried to resolve the issue of using the RecyclerView with my ArrayList. However I am getting the error of no adapter attached. I have tried to attach a Listener but that isn't working so I am trying to use the notifyDataSetChanged method but I am confused as to how to use it. I've tried to put it in the post execute but I get another error. Can some help me figure out how to use it?
Here is my Fragment:
public class WeatherAppFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private SearchView searchView = null;
private SearchView.OnQueryTextListener queryTextListener;
RecyclerView mRecyclerView;
String mStatusView;
private List<ForecastWeatherList> weatherList = new ArrayList<>();
private RecyclerViewAdapter mAdapter;
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public WeatherAppFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment WeatherAppFragment.
*/
// TODO: Rename and change types and number of parameters
public static WeatherAppFragment newInstance(String param1, String param2) {
WeatherAppFragment fragment = new WeatherAppFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_weather_app, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addItemDecoration(new DividerItemDecoration(mRecyclerView.getContext(), DividerItemDecoration.VERTICAL));
mRecyclerView.setAdapter(mAdapter);
new WeatherAppFragment.GetWeatherAync().execute(getActivity());
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu, menu);
MenuItem searchItem = menu.findItem(R.id.menu_search);
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) {
searchView = (SearchView) searchItem.getActionView();
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
queryTextListener = new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextChange(String newText) {
Log.i("onQueryTextChange", newText);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
Log.i("onQueryTextSubmit", query);
mStatusView = query;
return true;
}
};
searchView.setOnQueryTextListener(queryTextListener);
}
super.onCreateOptionsMenu(menu, inflater);
}
public class GetWeatherAync extends AsyncTask<Context, Void, ArrayList<ForecastWeatherList>> {
private String TAG = GetWeatherAync.class.getSimpleName();
public String api_key = "&APPID=ce7da0eaca788fc6342028eae6f3dd5c";
private Context context;
private final String serviceUrl = "http://api.openweathermap.org/data/2.5/forecast?q=" + "Baltimore" + api_key;
#Override
protected ArrayList<ForecastWeatherList> doInBackground(Context...params) {
context = params[0];
try {
Log.e(TAG, "I'm in background");
URL url = new URL(serviceUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setConnectTimeout(4000);
connection.setReadTimeout(4000);
connection.connect();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
ForecastWeatherListWrapper weatherWrapper = new Gson().fromJson(bufferedReader, ForecastWeatherListWrapper.class);
return (ArrayList<ForecastWeatherList>) weatherWrapper.getforecastWeatherLists();
} catch (Exception e) {}
return null;
}
#Override
protected void onPostExecute(ArrayList<ForecastWeatherList> result ) {
super.onPostExecute(result);
if (result != null) {
Log.e(TAG, "populate UI recycler view with gson converted data");
RecyclerViewAdapter weatherRecyclerViewAdapter = new RecyclerViewAdapter(result,context);
mRecyclerView.setAdapter(weatherRecyclerViewAdapter);
mAdapter.notifyDataSetChanged();
}
}
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_search:
// Not implemented here
return false;
default:
break;
}
searchView.setOnQueryTextListener(queryTextListener);
return super.onOptionsItemSelected(item);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
Here is my RecyclerViewAdapter:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ForecastRecycler> {
ArrayList<ForecastWeatherList> mForecastWeatherDataList;
private Context context;
public static class ForecastRecycler extends RecyclerView.ViewHolder{
public TextView currentTemp;
public TextView currentHumidity;
public TextView currentDescription;
public ImageView currentIcon;
public ForecastRecycler (View view) {
super (view);
currentTemp = (TextView) view.findViewById(R.id.current_temperature);
currentHumidity = (TextView) view.findViewById(R.id.current_humidity);
currentDescription = (TextView) view.findViewById(R.id.current_weather_description);
currentIcon = (ImageView) view.findViewById(R.id.current_weather_icon);
}
}
public RecyclerViewAdapter(List<ForecastWeatherList> mForecastWeatherDataList, Context context) {
this.mForecastWeatherDataList = (ArrayList<ForecastWeatherList>) mForecastWeatherDataList;
this.context = context;
}
#Override
public ForecastRecycler onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_item, parent, false);
final ForecastRecycler currentRecycler = new ForecastRecycler(view);
return currentRecycler;
}
#Override
public void onBindViewHolder( ForecastRecycler holder, int position) {
final ForecastWeatherList currentRecycler = mForecastWeatherDataList.get(position);
holder.currentTemp.setText((currentRecycler.getMain().getTempKf()));
holder.currentHumidity.setText(currentRecycler.getMain().getHumidity());
holder.currentDescription.setText(currentRecycler.getWeather().getDescription());
Picasso.with(holder.currentIcon.getContext()).load(currentRecycler.getWeather().getIcon());
}
#Override
public int getItemCount() {
return mForecastWeatherDataList.size();
}
}
notifyDataSetChanged() is used after setting-adding RecyclerView's Adapter data.
Try adding: notifyDataSetChanged() after
mRecyclerView.setAdapter(mAdapter);
Or whereever you update-add data to the Adapter. Or, you can try with this:
mAdapter.notifyDataSetChanged()
In onPostExecute.
it seems you forgot to update the adapter with your results...at onPostExecute :
update mForecastWeatherDataList then call notifyDataSetChanged()
I am using OkHttp to get HTML string and list the information in RecyclerView in a fragment.
However, when the app runs, it didn't show list information at first launch.
After I click other fragment page and go back to this fragment page, it show list.
But when I swipe down to see more list, the list repeat for twice (or more?) and the item background color disordered.
How can I fix it? Thanks!
My Adapter
public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
private List<NewsModel> mNewsList;
class ViewHolder extends RecyclerView.ViewHolder {
TextView newsNameText;
TextView newsDataText;
View listView;
public ViewHolder(View newsView) {
super(newsView);
newsNameText = (TextView) newsView.findViewById(R.id.news_Name);
newsDataText = (TextView) newsView.findViewById(R.id.news_Data);
listView = newsView;
}
}
public NewsAdapter(List<NewsModel> newsList) {
mNewsList = newsList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false);
final ViewHolder holder = new ViewHolder(view);
return holder;
}
public void setData(List<NewsModel> viewData) {
mNewsList.clear();
mNewsList.addAll(viewData);
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
NewsModel news = mNewsList.get(position);
holder.setIsRecyclable(true);
if(position % 2 == 0){
holder.listView.setBackgroundColor(0x80E0EEEE);
}
holder.newsNameText.setText(news.getName());
holder.newsDataText.setText(news.getData());
}
#Override
public int getItemCount() {
return mNewsList.size();
}
}
My fragment
public class NewsFragment extends Fragment {
List<NewsModel> resultList = new ArrayList<>();
List<NewsModel> htmlList = new ArrayList<>();
NewsAdapter adapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View newsView = inflater.inflate(R.layout.fragment_news, container, false);
RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
newsRecyclerView.setLayoutManager(layoutManager);
adapter = new NewsAdapter(getNews());
newsRecyclerView.setAdapter(adapter);
return newsView;
}
private List<NewsModel> getNews() {
new Thread(new Runnable() {
#Override
public void run() {
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true")
.build();
Response response = client.newCall(request).execute();
String resultString = response.body().string();
resultList.clear();
resultList.addAll(getResult(resultString));
adapter.notifyDataSetChanged();
/*new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
adapter.setData(resultList);
adapter.notifyDataSetChanged();
}
});//postdelayed (runnable long) cannot be applied to runnable*/
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
return resultList;
}
private List<NewsModel> getResult(final String response) {
XXXXXX
return htmlList;
}
}
The problem is that maybe you are adding many entries and since recyclerview is trying to reuse those views instead of redrawing again and again which cause sometimes view inconsistency. Here is the problem discussed Look into it if you are having the same problem.
to disable it or enable it to use in your bindViewHolder()
setIsRecyclable(Boolean enable)
And your second problem is that onCreateView() is called the second time when coming back from another fragment causing addition of duplicate data again so you need to clear the list before adding any new entries and Why it's not showing in the first run because you have added data in another thread and did not updated the adapter about it.
List<NewsModel> resultList = new ArrayList<>();
NewsAdapter adapter ;
public class NewsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View newsView = inflater.inflate(R.layout.fragment_news, container, false);
RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
newsRecyclerView.setLayoutManager(layoutManager);
adapter = new NewsAdapter(resultList);
newsRecyclerView.setAdapter(adapter);
getNews();
return newsView;
}
private void getNews(){
AsyncTask<Void,Void,String> asyncTask = new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(final Void... voids) {
String resultString = null;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true")
.build();
Response response = null;
try {
response = client.newCall(request).execute();
resultString = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
return resultString;
}
#Override
protected void onPostExecute(final String resultString) {
super.onPostExecute(resultString);
resultList.clear();
resultList.addAll(getResult(resultString));
adapter.notifyDataSetChanged();
}
}.execute();
}
The thread will change the resultList in some delay, but you already passed old data before that.
Please try as following...
public class NewsFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View newsView = inflater.inflate(R.layout.fragment_news, container, false);
RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
newsRecyclerView.setLayoutManager(layoutManager);
getNews(newsRecyclerView);
return newsView;
}
private void getNews(final RecyclerView newsRecyclerView){
new Thread(new Runnable() {
#Override
public void run() {
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true")
.build();
Response response = client.newCall(request).execute();
String resultString = response.body().string();
List<NewsModel> resultList = getResult(resultString);
NewsAdapter adapter = new NewsAdapter(resultList);
newsRecyclerView.setAdapter(adapter);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
private List<NewsModel> getResult(final String response) {
XXXXXXXXX
return List;
}
Main pattern is bad.
The easiest way for this code is to set (not add) items in adapter when it is downloaded and invoke on adapter notifyDataSetChanged() - all cells will be redraw.
So make adapter as field, add method to adapter setData() and:
...
Response response = client.newCall(request).execute();
String resultString = response.body().string();
resultList = getResult(resultString);
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
adapter.setData(results);
adapter.notifyDataSetChanged();
}
});
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
I am getting this error-Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
This is what i have done!
PeopleListFragment
**PeopleListFragment**
public class PeopleListFragment extends Fragment{
public static final String DISPLAY_URL = ServiceAPI.URL_CONTACTS;
private static final String TAG = "PeopleListActivity";
public static final boolean DEBUG = Constant.DEBUG;
private ProgressDialog progressDialog;
public PeopleAdapter adapter;
private GetAllPeopleTask mGetAllPeople = null;
private Intent intent;
public static ListView mContactlistView;
public PeopleListFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_people_list, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mContactlistView = (ListView) view.findViewById(R.id.people_list);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
List<People> contactList = new ArrayList<People>();
adapter = new PeopleAdapter(getActivity().getApplicationContext(),
R.layout.people_list_item, contactList);
mContactlistView.setAdapter(adapter);
mContactlistView.setTextFilterEnabled(true);
mContactlistView.setFastScrollEnabled(true);
mContactlistView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String empId = String.valueOf(adapter.getItem(position).getEmployeeId());
String name = String.valueOf(adapter.getItem(position).getFirstName());
intent = new Intent(getActivity(),
PeopleDetailsActivity.class);
intent.putExtra("EmployeeId", empId);
intent.putExtra("name", name);
startActivity(intent);
}
});
startAsyncTask();
TextView textView = new TextView(getContext());
textView.setText("Empty");
mContactlistView.setEmptyView(textView);
}
public void startAsyncTask() {
mGetAllPeople = new GetAllPeopleTask();
mGetAllPeople.execute(DISPLAY_URL, "12345678");
}
public class GetAllPeopleTask extends AsyncTask<String, Void, List<People>> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressDialog = new ProgressDialog(getActivity());
progressDialog.setMessage("Loading");
progressDialog.show();
}
#Override
protected ArrayList<People> doInBackground(String... params) {
ArrayList<People> peopleList = new ArrayList<>();
try {
URL url = new URL(params[0]);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setReadTimeout(40000);
httpURLConnection.setConnectTimeout(50000);
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setRequestProperty("Content-Type", "application/json");
httpURLConnection.setRequestProperty("Accept", "application/json");
httpURLConnection.setDoOutput(true);
JSONObject request = new JSONObject();
request.put("session", params[1]);
String bodyParams = request.toString();
if (DEBUG) {
Log.i(TAG, bodyParams);
}
httpURLConnection.setRequestProperty("Content-Length",
String.valueOf(bodyParams.getBytes().length));
DataOutputStream outputStream = new DataOutputStream(httpURLConnection.getOutputStream());
outputStream.writeBytes(bodyParams);
outputStream.flush();
outputStream.close();
httpURLConnection.connect();
if (httpURLConnection.getResponseCode() == 200) {
Log.i(TAG, "Success");
} else {
Log.i(TAG, "Error Code :" + httpURLConnection.getResponseCode());
}
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null) {
builder.append(line);
}
Log.i(TAG, "Builder String : " + builder.toString());
JSONObject jsonObject = new JSONObject(builder.toString());
Log.i(TAG, "Response JSON : " + jsonObject.toString());
if (jsonObject.has("responseData")) {
JSONArray responseDataArr = jsonObject.optJSONArray("responseData");
for (int i = 0; i < responseDataArr.length(); i++) {
JSONObject peopleJSON = responseDataArr.optJSONObject(i);
People people = new People();
people.setEmployeeId(peopleJSON.optString("employeeId"));
people.setFirstName(peopleJSON.optString("firstName"));
people.setLastName(peopleJSON.optString("lastName"));
// Log.i("hebsiba ", "People first name" + people.getFirstName() + ", last name is " + people.getLastName()) ;
if((!people.getFirstName().isEmpty()) && (!people.getLastName().isEmpty())) {
peopleList.add(people);
}
if (DEBUG) {
Log.i(TAG, "People " + people.getEmployeeId());
}
}
}
} catch (IOException | JSONException e) {
Log.e(TAG, e.toString());
}
return peopleList;
}
#Override
protected void onPostExecute(List<People> people) {
super.onPostExecute(people);
Collections.sort(people, new Comparator<People>() {
#Override
public int compare(People lhs, People rhs) {
return lhs.getFirstName().compareToIgnoreCase(rhs.getFirstName());
}
});
adapter.addAll(people);
if (DEBUG) {
Log.i(TAG, adapter.getCount() + " ");
}
Log.v(TAG, String.valueOf(people.size()));
progressDialog.dismiss();
}
}
}
This is the PeopleAdapter
**PeopleAdapter**
public class PeopleAdapter extends ArrayAdapter<People> implements Filterable {
private PeopleListActivity activity;
private PeopleFilter peopleFilter;
private List<People> peopleList;
private List<People> filteredList;
public PeopleAdapter(Context applicationContext, int people_list_item, List<People> contactList) {
super(applicationContext, people_list_item, contactList);
filteredList = contactList;
getFilter();
}
#Override
public int getCount() {
return filteredList.size();
}
#Override
public People getItem(int i) {
return filteredList.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
People peopleList = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.people_list_item, null);
holder = new ViewHolder();
holder.firstName = (TextView) convertView.findViewById(R.id.firstName);
holder.lastName = (TextView) convertView.findViewById(R.id.lastName);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.firstName.setText(peopleList.getFirstName());
holder.lastName.setText(peopleList.getLastName());
return convertView;
}
/**
* Get custom filter
* #return filter
*/
#Override
public Filter getFilter() {
if (peopleFilter == null) {
peopleFilter = new PeopleFilter();
}
return peopleFilter;
}
static class ViewHolder {
TextView firstName;
TextView lastName;
}
private class PeopleFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint!=null && constraint.length()>0) {
ArrayList<People> tempList = new ArrayList<>();
// search content in friend list
for (People user : peopleList) {
if (user.getFirstName().toLowerCase().contains(constraint.toString().toLowerCase())) {
tempList.add(user);
}
}
filterResults.count = tempList.size();
filterResults.values = tempList;
} else {
filterResults.count = peopleList.size();
filterResults.values = peopleList;
}
return filterResults;
}
/**
* Notify about filtered list to ui
* #param constraint text
* #param results filtered result
*/
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
filteredList = (ArrayList<People>) results.values;
notifyDataSetChanged();
}
}
}
And this is PeopleListActivity
**PeopleListActivity**
public class PeopleListActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
private PeopleListFragment fragment;
private FragmentManager displayFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.argb(255, 180, 110, 60));
}
setContentView(R.layout.activity_people);
Toolbar toolbar = (Toolbar) findViewById(R.id.people_toolbar);
setSupportActionBar(toolbar);
toolbar.setNavigationIcon(R.drawable.ic_back_arrow);
getSupportActionBar().setDisplayShowTitleEnabled(false);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(PeopleListActivity.this, NavigationActivity.class);
startActivity(intent);
}
});
displayFragment = getSupportFragmentManager();
fragment = new PeopleListFragment();
displayFragment.beginTransaction().add(R.id.people_fragment, fragment).commit();
if (savedInstanceState == null) {
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
SearchManager searchManager =(SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView =(SearchView) menu.findItem(R.id.search).getActionView();
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
// searchView.setIconifiedByDefault(false);
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextListener(this);
return true;
// return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
PeopleAdapter peopleAdapter = (PeopleAdapter) PeopleListFragment.mContactlistView.getAdapter();
peopleAdapter.getFilter().filter(newText);
return true;
}
}
Could anyone help me with this..?
Assign some value to filteredList when you create the Adapter
Example:
public PeopleAdapter(Context applicationContext, int people_list_item, List<People> contactList) {
super(applicationContext, people_list_item, contactList);
filteredList = contactList;
getFilter();
}
filteredList is null when getCount() is called. Instantiate it first or make sure filteredList has some content.
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I am using a RecyclerView and a Async Task to update the view in this RecyclerView but I am getting a null pointer exception at a RecyclerView.setAdapter. My FetchMoviePoster class contains the Async Task and PhotoAlbumAdapter contains the adapter for the Recycler View.
Can anyone please help me with that
MainActivityFragment
public class MainActivityFragment extends Fragment implements PhotoAlbumAdapter.OnItemClickListener {
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
PhotoAlbumAdapter mAdapter;
FetchMoviePoster movie_fetch;
public MainActivityFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.movie_sort, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_sort) {
return true;
}
if(id== R.id.pop){
updateMovie("popularity.desc");
return true;
}
if(id== R.id.vote){
updateMovie("vote_average.desc");
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
recyclerView = (RecyclerView) rootView.findViewById(R.id.recyle_view);
recyclerView.setHasFixedSize(true);
layoutManager = new GridLayoutManager(getActivity(), 2, GridLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(layoutManager);
movie_fetch= new FetchMoviePoster();
registerForContextMenu(recyclerView);
updateMovie("vote_count.desc");
return rootView;
}
private void updateMovie(String c) {
movie_fetch.execute(c);
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
getActivity().getMenuInflater().inflate(R.menu.pop_up_menu, menu);
}
public void update_the_Adaptor(String[] st){
mAdapter = new PhotoAlbumAdapter(new ArrayList<>(Arrays.asList(st)), getContext());
recyclerView.setAdapter(mAdapter);
mAdapter.SetOnItemClickListener(MainActivityFragment.this);
}
#Override
public void onItemClick(View view, int position) {
Log.v("Actual position", Integer.toString(position));
Intent detail= new Intent(getActivity(),DetailActivity.class);
detail.putExtra("position",position);
detail.putExtra("poster", movie_fetch.resultStrs);
detail.putExtra("title",movie_fetch. movie_title);
detail.putExtra("plot", movie_fetch.movie_plot);
detail.putExtra("user_rating", movie_fetch.user_rating);
detail.putExtra("release", movie_fetch.release_date);
startActivity(detail);
}
}
My PhotoAlbumAdapterClass
public class PhotoAlbumAdapter extends RecyclerView.Adapter<PhotoAlbumAdapter.ViewHolder> {
ArrayList<String> image;
Context context;
OnItemClickListener mClickListener;
public PhotoAlbumAdapter(ArrayList<String> imageView, Context context) {
image=imageView;
this.context=context;
}
#Override
public PhotoAlbumAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.image_holder,parent,false);
ViewHolder vh=new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final PhotoAlbumAdapter.ViewHolder holder, int position) {
String st=image.get(position);
Uri uri=Uri.parse(st);
Picasso.with(context).load(uri)
.into(holder.img);
AnimationsUtils.animate(holder);
}
#Override
public int getItemCount() {
return image.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
ImageView img;
public ViewHolder(View itemView) {
super(itemView);
img = (ImageView) itemView.findViewById(R.id.imageView);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if(mClickListener !=null)
mClickListener.onItemClick(view, getAdapterPosition()); //OnItemClickListener mItemClickListener;
}
}
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
public void SetOnItemClickListener(final OnItemClickListener m){
mClickListener=m;
}
}
My FetchMoviePoster class
public class FetchMoviePoster extends AsyncTask<String, Void, String[]> {
private final String LOG_TAG = FetchMoviePoster.class.getSimpleName();
String choice;
String[] resultStrs;
String[] movie_title;
String[] movie_plot;
String[] user_rating;
String[] release_date;
#Override
protected String[] doInBackground(String... code) {
HttpURLConnection urlConnection = null;
BufferedReader reader = null;
String[] image_poster = new String[0];
String API = "api_key";
String SORT="sort_by";
choice=code[0];
String forecastJsonStr = null;
try {
Uri fetch_url = Uri.parse("http://api.themoviedb.org/3/discover/movie?");
Uri builder = fetch_url.buildUpon().
appendQueryParameter(SORT,choice)
.appendQueryParameter(API, BuildConfig.THE_MOVIE_DB_API_KEY).build();
URL url = new URL(builder.toString());
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
StringBuffer buffer = new StringBuffer();
if (inputStream == null) {
// Nothing to do.
return null;
}
reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
buffer.append(line + "/n");
}
if (buffer.length() == 0) {
return null;
}
forecastJsonStr = buffer.toString();
try {
image_poster = getUrlForImage(forecastJsonStr);
} catch (JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
Log.e(LOG_TAG, "Error ", e);
// If the code didn't successfully get the weather data, there's no point in attempting
// to parse it.
forecastJsonStr = null;
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (final IOException e) {
Log.e(LOG_TAG, "Error closing stream", e);
}
}
}
return image_poster;
}
private String[] getUrlForImage(String forecastJsonStr) throws JSONException {
final String OWM_POSTER = "results";
final String FILE_PATH = "poster_path";
final String ORIGINAL_TITLE="original_title";
final String OVERVIEW="overview";
final String User_RATING="vote_average";
final String RELEASE="release_date";
JSONObject forecastJson = new JSONObject(forecastJsonStr);
JSONArray movieArray = forecastJson.getJSONArray(OWM_POSTER);
resultStrs = new String[movieArray.length()];
movie_title=new String[movieArray.length()];
movie_plot=new String[movieArray.length()];
user_rating=new String[movieArray.length()];
release_date=new String[movieArray.length()];
for (int i = 0; i < movieArray.length(); i++) {
JSONObject movie = movieArray.getJSONObject(i);
String file_name = movie.getString(FILE_PATH);
String title=movie.getString(ORIGINAL_TITLE);
String plot=movie.getString(OVERVIEW);
String userRating=movie.getString(User_RATING);
String release=movie.getString(RELEASE);
resultStrs[i] = "http://image.tmdb.org/t/p/w185/" +file_name;
movie_title[i]=title;
movie_plot[i]=plot;
user_rating[i]= userRating;
release_date[i]=release;
}
return resultStrs;
}
#Override
protected void onPostExecute(String[] resultStrs) {
if (resultStrs != null) {
new MainActivityFragment().update_the_Adaptor(resultStrs);
}
}
}
LogCat
12-12 20:24:22.066 4229-4229/com.example.dell.movielove W/dalvikvm:
threadid=1: thread exiting with uncaught exception (group=0x41915c08)
12-12 20:24:22.136 4229-4229/com.example.dell.movielove E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.dell.movielove, PID: 4229
java.lang.NullPointerException
at
com.example.dell.movielove.MainActivityFragment.update_the_Adaptor(MainActivityFragment.java:99)
at
com.example.dell.movielove.FetchMoviePoster.onPostExecute(FetchMoviePoster.java:138)
at
com.example.dell.movielove.FetchMoviePoster.onPostExecute(FetchMoviePoster.java:19)
at android.os.AsyncTask.finish(AsyncTask.java:632)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at
android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:146)
at android.app.ActivityThread.main(ActivityThread.java:5641)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1288)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1104)
at dalvik.system.NativeStart.main(Native Method)
Check onPostExecute method of Async task:
#Override
protected void onPostExecute(String[] resultStrs) {
if (resultStrs != null) {
//creating new instance not using old
new MainActivityFragment().update_the_Adaptor(resultStrs);
}
}
on new instance of MainActivityFragment you are calling update_the_Adaptor()
public void update_the_Adaptor(String[] st){
// st is not null
mAdapter = new PhotoAlbumAdapter(new ArrayList<>(Arrays.asList(st)), getContext());
recyclerView.setAdapter(mAdapter);//null recycler view as onCreate is not called
mAdapter.SetOnItemClickListener(MainActivityFragment.this);
}
You call
new MainActivityFragment().update_the_Adaptor(resultStrs);
But you MainActivityFragment didn't create because you didn't use FragmentManager to commit your fragment so onCreateView will not be called and recyclerView is null, your NullPointerException will be thrown from update_the_Adaptor.
I am using this Tutorial and its sourcecodes to make listview in android. I had implemented using this tutorial but during updating the setListAdapter i cannot update the listview dynamically.
I have gone through many stackoverflow questions and they are giving adapter.notifyDataSetChanged() as the solution. But i am unable to implement it in AsyncTask.
ItemListFragment.java
public class ItemListFragment extends ListFragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = super.onCreateView(inflater, container, savedInstanceState);
setListAdapter(new ItemAdapter(getActivity(), setArray(getActivity())));
return v;
}
public ArrayList<Item> setArray(Context context)
{
ArrayList<Item> items = new ArrayList<Item>();
Realm realm = Realm.getInstance(context);
RealmResults<Books> bs = realm.where(Books.class).findAll();
for (int i = 0; i < bs.size(); i++) {
Bitmap url = BitmapFactory.decodeFile(bs.get(i).getCover());
String title = bs.get(i).getName();
String description = bs.get(i).getAuthor();
Item item = new Item(url, title, description);
items.add(item);
}
realm.close();
return items;
}
}
ItemAdapter.java
public class ItemAdapter extends ArrayAdapter<Item> {
public ItemAdapter(Context context, List<Item> items) {
super(context, 0, items);
}
public View getView(int position, View convertView, ViewGroup parent)
{
ItemView itemView = (ItemView) convertView;
if (null == itemView)
{
itemView = ItemView.inflate(parent);
}
itemView.setItem(getItem(position));
return itemView;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
if (BuildConfig.DEBUG)
ViewServer.get(this).addWindow(this);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
else if (id == R.id.update) {
Update update = new Update(getApplicationContext(), MainActivity.this);
update.execute();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onDestroy() {
super.onDestroy();
if (BuildConfig.DEBUG)
ViewServer.get(this).removeWindow(this);
}
#Override
protected void onResume() {
super.onResume();
if (BuildConfig.DEBUG)
ViewServer.get(this).setFocusedWindow(this);
}
}
Update.java
public class Update extends AsyncTask<Void,Void,Void>{
private Context context;
public Activity activity;
public Update(Context context, Activity activity)
{
this.context = context;
this.activity = activity;
}
#Override
protected Void doInBackground(Void... params) {
ServerAddress = context.getString(R.string.ServerAddress);
StringExtras = context.getString(R.string.CheckBook);
Realm realm = null;
try {
URL url = new URL(ServerAddress + StringExtras);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Content-length", "0");
httpURLConnection.setUseCaches(false);
httpURLConnection.setAllowUserInteraction(false);
httpURLConnection.setConnectTimeout(1000);
httpURLConnection.setReadTimeout(1000);
httpURLConnection.connect();
int responseCode = httpURLConnection.getResponseCode();
Log.i("Response Code",responseCode+"");
BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
String InputLine;
StringBuilder response = new StringBuilder();
while ((InputLine = br.readLine()) != null)
{
response.append(InputLine);
}
br.close();
httpURLConnection.disconnect();
Log.i("Response Data", response.toString());
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
JSONArray array = new JSONArray(response.toString());
//booksList = Arrays.asList(books);
//JSONArray jsonArray = object.getJSONArray("cover");
realm = Realm.getInstance(context);
for (int i=0; i< array.length(); i++ ) {
JSONObject object = array.getJSONObject(i);
Books books = gson.fromJson(object.toString(), Books.class);
Publish(books, realm);
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (realm != null){
realm.close();
}
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
//i want to call the setarray that contains my database data which has been updated on `doinbackground` and update the listview accordingly.
//The below codes are just the codes that i have tried but what should i do to update the listview.
activity.runOnUiThread(new Runnable() {
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public void run() {
ItemListFragment activity1 = new ItemListFragment();
ArrayList<Item> arrayList = activity1.setArray(context);
List<Item> list = new ArrayList<Item>();
int i = 0;
for (Item item : arrayList)
{
list.add(arrayList.get(i));
i++;
}
activity1.arrayAdapter.addAll(list);
activity1.arrayAdapter.notifyDataSetChanged();
}
});
}
I am trying to update the listview from postexcution. So, how can i update the view through it.
Error From AsyncTask
just incase you need but it's not the problem
8-30 16:31:47.976 1167-1167/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
at np.com.thefourthgeneration.Update$1.run(Update.java:124)
at android.app.Activity.runOnUiThread(Activity.java:4673)
at np.com.thefourthgeneration.Update.onPostExecute(Update.java:108)
at np.com.thefourthgeneration.Update.onPostExecute(Update.java:34)
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)
layout/activity_list
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
layout/list_fragment
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
MainActivity
public class MainActivity extends AppCompatActivity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
FragmentManager fm = getFragmentManager();
itemListFragment = (ItemListFragment) fm.findFragmentByTag(ItemListFragment.class.getSimpleName());
if (itemListFragment == null) {
itemListFragment = new ItemListFragment();
FragmentTransaction fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, itemListFragment, ItemListFragment.class.getSimpleName());
fragmentTransaction.commit();
}
if (BuildConfig.DEBUG) {
ViewServer.get(this).addWindow(this);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
if (BuildConfig.DEBUG) {
ViewServer.get(this).removeWindow(this);
}
}
#Override
protected void onResume() {
super.onResume();
if (BuildConfig.DEBUG) {
ViewServer.get(this).setFocusedWindow(this);
}
}
}
ItemListFragment
public class ItemListFragment extends Fragment
{
private ListView listView;
private ItemAdapter itemAdapter;
private ArrayList<Item> itemArrayList = new ArrayList<>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.list_fragment, container, false);
itemAdapter = new ItemAdapter(getActivity(), itemArrayList);
listView = (ListView) view.findViewById(R.id.listView);
listView.setAdapter(itemAdapter);
return view;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_main, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_settings:
return true;
case R.id.update:
new Update(getActivity()).execute();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public class Update extends AsyncTask<Void, Void, Void>
{
private Context context;
public Update(Context context) {
this.context = context;
}
#Override
protected Void doInBackground(Void... params) {
ServerAddress = context.getString(R.string.ServerAddress);
StringExtras = context.getString(R.string.CheckBook);
Realm realm = null;
try {
URL url = new URL(ServerAddress + StringExtras);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("Content-length", "0");
httpURLConnection.setUseCaches(false);
httpURLConnection.setAllowUserInteraction(false);
httpURLConnection.setConnectTimeout(1000);
httpURLConnection.setReadTimeout(1000);
httpURLConnection.connect();
int responseCode = httpURLConnection.getResponseCode();
Log.i("Response Code", responseCode + "");
BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
String InputLine;
StringBuilder response = new StringBuilder();
while ((InputLine = br.readLine()) != null) {
response.append(InputLine);
}
br.close();
httpURLConnection.disconnect();
Log.i("Response Data", response.toString());
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
JSONArray array = new JSONArray(response.toString());
//booksList = Arrays.asList(books);
//JSONArray jsonArray = object.getJSONArray("cover");
realm = Realm.getInstance(context);
for (int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
Books books = gson.fromJson(object.toString(), Books.class);
Publish(books, realm);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (realm != null) {
realm.close();
}
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
itemArrayList.clear();
itemArrayList.addAll(getArray(context));
itemAdapter.notifyDataSetChanged();
}
public ArrayList<Item> getArray(Context context) {
ArrayList<Item> items = new ArrayList<Item>();
Realm realm = Realm.getInstance(context);
RealmResults<Books> bs = realm.where(Books.class).findAll();
for (int i = 0; i < bs.size(); i++) {
Bitmap url = BitmapFactory.decodeFile(bs.get(i).getCover());
String title = bs.get(i).getName();
String description = bs.get(i).getAuthor();
Item item = new Item(url, title, description);
items.add(item);
}
realm.close();
return items;
}
}
public class ItemAdapter extends ArrayAdapter<Item>
{
public ItemAdapter(Context context, List<Item> items) {
super(context, 0, items);
}
public View getView(int position, View convertView, ViewGroup parent) {
ItemView itemView = (ItemView) convertView;
if (null == itemView) {
itemView = ItemView.inflate(parent);
}
itemView.setItem(getItem(position));
return itemView;
}
}
}
Its not the 100% work code, because i dont fully understand all structures (like Realm) and I dont test it, but its the main idea.