i have request in retrofit where return List which assign for my dataSet field. i did it in onResponse method. But initializing of recycle view in MainActivity is faster than request and view is showing nothing. What i can to do for waiting onResponse method.
I have this two methods in class NewsRepository.java
private void setNews(){
GetDataService service = RetrofitClientInstance.getRetrofitInstance().create(GetDataService.class);
Call<ItemsAPI> call = service.getAllItems();
call.enqueue(new Callback<ItemsAPI>() {
#Override
public void onResponse(Call<ItemsAPI> call, Response<ItemsAPI> response) {
Log.d(TAG, "onResponse");
items = response.body();
dataSet = items.getItems();
Log.d(TAG, dataSet.get(0).getTitle());
}
#Override
public void onFailure(Call<ItemsAPI> call, Throwable t) {
Log.d(TAG, "onFailure "+ t.getMessage());
}
});
}
public MutableLiveData<List<News>> getNews(){
setNews();
MutableLiveData<List<News>> data = new MutableLiveData<>();
data.setValue(dataSet);
return data;
}
And have this in MainActivityModelView.java
public void init(){
if(mNews != null){
return;
}
mRepo = NewsRepository.getInstance();
mNews = mRepo.getNews();
}
And this is MyActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private RecyclerView mRecycleView;
private RecycleViewAdapter mAdapter;
private MainActivityViewModel mMainActivityViewModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecycleView = findViewById(R.id.recyclev_view);
mMainActivityViewModel = ViewModelProviders.of(this).get(MainActivityViewModel.class);
mMainActivityViewModel.init();
mMainActivityViewModel.getNews().observe((LifecycleOwner) this, new Observer<List<News>>() {
#Override
public void onChanged(#Nullable List<News> news) {
mAdapter.notifyDataSetChanged();
}
});
mMainActivityViewModel.getIsUpdating().observe((LifecycleOwner) this, new Observer<Boolean>() {
#Override
public void onChanged(#Nullable Boolean aBoolean) {
if(aBoolean){
}
else{
mRecycleView.smoothScrollToPosition(mMainActivityViewModel.getNews().getValue().size()-1);
}
}
});
initRecyclerView();
Log.d(TAG, "RecycleView is inited");
}
private void initRecyclerView(){
mAdapter = new RecycleViewAdapter(this, mMainActivityViewModel.getNews().getValue());
RecyclerView.LayoutManager linearLayoutManager = new LinearLayoutManager(this);
mRecycleView.setLayoutManager(linearLayoutManager);
mRecycleView.setAdapter(mAdapter);
}
}
The Activity is init is faster then my request.
2019-05-18 09:32:12.299 13859-13859/com.krasnov.rxjavalearning D/MainActivity: RecycleView is inited
2019-05-18 09:32:13.098 13859-13859/com.krasnov.rxjavalearning D/NewsRepository: onResponse
I think it's better to move this code above othre code below findViewById
initRecyclerView();
Log.d(TAG, "RecycleView is inited");
In this function its better to not use this constractor
mAdapter = new RecycleViewAdapter(this, mMainActivityViewModel.getNews().getValue());
Use this instead (create this constractor)
mAdapter = new RecycleViewAdapter(this);
And when your data arrive fire this function in adapter
public void setData( List<News> list) {
this.list= list
notifyDataSetChanged()
}
So your code is like
mMainActivityViewModel.getNews().observe((LifecycleOwner) this, new Observer<List<News>>() {
#Override
public void onChanged(#Nullable List<News> news) {
mAdapter.setData(news)
}
});
in your onResponse you should notify adapter add this:
yourAdapter.notifyDataSetChanged();
On resume call the retrofit service,
after response create a callback
method in ViewModel to notify in Activty class, after notified then
initialise recyclerview.
.
Related
I get error when trying to call API interface get request. I am trying to pass a value through GET method. But I get this error in logcat Caused by: java.lang.IllegalArgumentException: HTTP method annotation is required (e.g., #GET, #POST, etc.). for method ApiInterface.name
Here is my java code. Here I call the function namely getname()to pass a string value through GET request. Here I also have one more function getdata() which display output in the recyclerview.
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
ListAdapter1 listAdapter;
// List<SupermarketModels> supermarketModelsList = new ArrayList<>();
ApiInterface apiInterface;
String hi;
Button badd;
EmptyAdapterl emptyAdapter = new EmptyAdapterl();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
badd=findViewById(R.id.btadd);
badd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent= new Intent(MainActivity.this,Insert.class);
startActivity(intent);
}
});
String tablen= getIntent().getStringExtra("name");
// supermarketModelsList.add(new SupermarketModels(1,"sugar cane","20kg",
// "50rs","31/12/2021"));
//
// supermarketModelsList.add(new SupermarketModels(2,"sugar cane","20kg",
// "50rs","31/12/2021"));
// supermarketModelsList.add(new SupermarketModels(3 ,"sugar cane","20kg",
// "50rs","31/12/2021"));
initialization();
hi=tablen;
Toast.makeText(MainActivity.this,"oo"+hi,Toast.LENGTH_SHORT).show();
getname(hi);
// recyclerView.setAdapter(emptyAdapter);
// getdata();
}
private void initialization(){
recyclerView = findViewById(R.id.recyclerview1);
Retrofit retrofit = APIClient.getclient();
apiInterface = retrofit.create(ApiInterface.class);
// apiInterface = APIClient.getRetrofitInstance().create(ApiInterface.class);
}
private void setadapter(List<SupermarketModels> supermarketModels){
listAdapter = new ListAdapter1(this, supermarketModels,hi);
// LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
#SuppressLint("WrongConstant")
RecyclerView.LayoutManager lm = new LinearLayoutManager(getApplicationContext(), LinearLayout.VERTICAL, false);
recyclerView.setLayoutManager(lm);
// linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(lm);
recyclerView.setAdapter(listAdapter);
}
private void getname(String n) {
apiInterface.name(n).enqueue(new Callback<DeleteResponse>() {
#Override
public void onResponse(Call<DeleteResponse> call, Response<DeleteResponse> response) {
try {
if (response.body().getStatus().equals("1")){
Toast.makeText(MainActivity.this,"Successfully inserted",Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(MainActivity.this,"Error while inserting",Toast.LENGTH_SHORT).show();
}
} catch (Exception e){
}
}
#Override
public void onFailure(Call<DeleteResponse> call, Throwable t) {
}
});
}
private void getdata(){
apiInterface.getList().enqueue(new Callback<GetListResponse>() {
#Override
public void onResponse(Call<GetListResponse> call, Response<GetListResponse> response) {
try {
if (response!= null){
if (response.body().getStatus().equals("1")){
// category_adapter category_adapter = new category_adapter(getContext(),datalist);
setadapter(response.body().getData());
}
else {
Toast.makeText(MainActivity.this, response.body().getMessage(), Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e){
Log.e("exp", e.getLocalizedMessage());
}
}
#Override
public void onFailure(Call<GetListResponse> call, Throwable t) {
}
});
}
}
This is my apiInterface class
public interface ApiInterface {
#GET("user-controller.php?operation=list")
Call<GetListResponse> getList();
Call<DeleteResponse> name(#Field("name") String name1);
}
make sure you are using Retrofit2 in your #GET Imports (maybe you are using the wrong #Get)
I am trying to call an API in APICaller.java from MainActivity.java. And then to put the data into recyclerview in MainActivity.java. However, it seems like it fails to call the API and restaurantList is empty. How can I go about to fix this? Thank you in advance.
MainActivity.java
public class MainActivity extends AppCompatActivity {
RecyclerView recyclerView;
List<Restaurant> restaurantList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerView);
restaurantList = new ArrayList<>();
APICaller apiCaller = new APICaller();
apiCaller.getRestaurants(new APICaller.OnRestaurantListReceivedCallback() {
#Override
public void onRestaurantListReceived(List<Restaurant> list) {
String name = list.get(0).toString();
PutDataIntoRecyclerView(list);
}
});
}
private void PutDataIntoRecyclerView (List<Restaurant> restaurantList) {
Adapter adapter = new Adapter(this, restaurantList);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
}
APICaller.java
public class APICaller {
private List<Restaurant> restaurantList;
interface OnRestaurantListReceivedCallback{
void onRestaurantListReceived(List<Restaurant> list);
}
public void getRestaurants(OnRestaurantListReceivedCallback callback){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://example123.com/wp-json/wp/")
.addConverterFactory(GsonConverterFactory.create())
.build();
WordpressAPICall wordpressAPICall = retrofit.create(WordpressAPICall.class);
Call<List<Restaurant>> call = wordpressAPICall.getData();
call.enqueue(new Callback<List<Restaurant>>() {
#Override
public void onResponse(Call<List<Restaurant>> call, Response<List<Restaurant>> response) {
List<Restaurant> restaurantModels = response.body();
for(int i = 0; i < restaurantModels.size(); i++){
int id = restaurantModels.get(i).getId();
String title = restaurantModels.get(i).getTitle().getRendered();
restaurantList.add(restaurantModels.get(i));
}
callback.onRestaurantListReceived(restaurantList);
}
#Override
public void onFailure(Call<List<Restaurant>> call, Throwable t) {
Log.d("ON FAILURE API CALL", t.toString());
}
});
}
I have a problem with Recyclerview item click. I fetch data to list() method and add via addItem() method in recyclerview custom adapter when scroll down in addOnScrollListener. I get item position with click interface on Fragment. First fetch data work perfectly but when fetch loadmore, can't retrive item positon to new data with onButtonLClick() method.
// in onBindViewHolder;
holder.lnl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
rcylviewItemNotify.onButtonLClick(position);
}catch (Throwable e){
//interface can be null
}
}
});
// addItem() method in adapter;
public void addItem(List<Image> img) {
for (Image im : img) {
arrayList.add(im);
}
notifyDataSetChanged();
}
// interface code;
public interface RcylviewItemNotify {
void onButtonLClick(int position);
}
// in Fragment code;
public void list() {
GetServices service = RetrofitInstance.getRetrofitInstance().create(GetServices.class);
Call<Images> call = service.getImages();
call.enqueue(new Callback<Images>() {
#Override
public void onResponse(Call<Images> call, Response<Images> response) {
Images body = response.body();
records = body.getImages();
adapter.addItem(records);
}
#Override
public void onFailure(Call<Images> call, Throwable t) {
Toast.makeText(getActivity(), "Network hatası onFailure", Toast.LENGTH_SHORT).show();
reflesh.setRefreshing(false);
}
});
}
#Override
public void onButtonLClick(int position) {
final String clickId = String.valueOf(records.get(position).getID());
Toast.makeText(getActivity(), "ID: " + clickId, Toast.LENGTH_SHORT).show();
}
// recycler settings;
public void loadView() {
layoutManager = new GridLayoutManager(getActivity(), 2);
recyclerView.setLayoutManager(layoutManager);
Collections.reverse(records);
adapter = new RecyclerViewAdapter(this,(ArrayList<Image>) records, getActivity());
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
reflesh.setRefreshing(false);
}
I'm not sure if this is your issue but you should be using the ViewHolder to get the position. Inside of your onBindViewHolder:
#Override
public void onClick(View view){
int itemPosition = holder.getAdapterPosition();
// Then do whatever you need to with the position
}
I have a mind-boggling problem I can't seem to solve.
The data in my RecyclerView is not updating, and after an entire day of debugging, I can't find the problematic code. The API returns the correct data, and I parse the correct data in a wallItemList which I pass to the Adapter.
How It Should Behave
After changing the language setting to either one of the 2 (English or Dutch), the items in my Recyclerview should update with it and the title of the element should change to the translated string.
What I Have Tried
Creating a refresh function inside the adapter, and update the wallItemList manually by passing the created wallItemList from the MainActivity and calling notifyDataSetChanged()
Calling notifyDataSetChanged() before, in and after the OnClickListener in the MyRecyclerViewAdapter
Setting the item in onBindViewHolder in the MyRecyclerViewAdapter
Strangely enough, when logging the language of the wallItem just before adapter.setOnItemClickListener in populateRecyclerView(), the language is right. But when I get the string from the object in MyRecyclerViewAdapter's onBindViewHolder, it shows the wrong language.
Here is my MainActivity.java:
public class MainActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {
private List<WallItem> WallItemList;
private RecyclerView mRecyclerView;
private MyRecyclerViewAdapter adapter;
private ProgressBar progressBar;
// LifeCycle variables
private String JSONResults = "";
final static private String JSON_KEY_RESULTS = "";
final static private String WALL_ITEM_LIST_KEY = "";
// SharedPrefences variables
private String APIUrlPreferenceString = "";
private String langPreferenceString = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
// Setup shared preferences
setupSharedPreferences();
// Load the recyclerView
loadRecyclerView(savedInstanceState);
}
private void setLanguageSettings(String lang)
{
//create a string for country
String country = "";
if(lang.equals("en"))
{
country = "EN";
}
else if(lang.equals("nl"))
{
country = "NL";
}
//use constructor with country
Locale locale = new Locale(lang, country);
Locale.setDefault(locale);
Configuration config = new Configuration();
config.locale = locale;
getBaseContext().getResources().updateConfiguration(config,
getBaseContext().getResources().getDisplayMetrics());
}
private void setupSharedPreferences()
{
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
APIUrlPreferenceString = sharedPreferences.getString(getString(R.string.pref_api_url_key), getString(R.string.pref_api_url_def_value));
sharedPreferences.registerOnSharedPreferenceChangeListener(this);
// Language settings
if(sharedPreferences.getBoolean(getString(R.string.pref_lang_check_key), true))
{
// Use device settings
setLanguageSettings(Resources.getSystem().getConfiguration().locale.getLanguage());
langPreferenceString = Resources.getSystem().getConfiguration().locale.getLanguage();
}
else
{
// Use preference settings
setLanguageSettings(sharedPreferences.getString(getString(R.string.pref_lang_list_key), getString(R.string.pref_lang_label_en)));
langPreferenceString = sharedPreferences.getString(getString(R.string.pref_lang_list_key), getString(R.string.pref_lang_label_en));
}
}
private void loadRecyclerView(Bundle savedInstanceState)
{
// Lifecycle event to preserve data to prevent repeating API calls
if(savedInstanceState != null && savedInstanceState.containsKey(WALL_ITEM_LIST_KEY) && savedInstanceState.containsKey(JSON_KEY_RESULTS))
{
progressBar.setVisibility(View.GONE);
// Set again in order to preserve state on future rotations
JSONResults = savedInstanceState.getString(JSON_KEY_RESULTS);
// Set wallItemList again in order to preserve state on future rotations
WallItemList = savedInstanceState.getParcelableArrayList(WALL_ITEM_LIST_KEY);
populateRecyclerView();
}
else
{
// First execution
new DownloadTask().execute();
}
}
public class DownloadTask extends AsyncTask<Void, Void, Boolean> {
#Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected Boolean doInBackground(Void... params) {
boolean result;
String blindWallResults;
try {
// Error fix, because NetworkUtils.buildUrl returns null when failing
if(null == NetworkUtils.buildUrl(APIUrlPreferenceString))
return false;
// Get response from API
blindWallResults = NetworkUtils.getResponseFromHttpUrl(NetworkUtils.buildUrl(APIUrlPreferenceString));
// Send to parser
JSONResults = blindWallResults;
parseResult(blindWallResults);
result = true;
} catch (IOException e) {
e.printStackTrace();
result = false;
}
// When failed
return result;
}
#Override
protected void onPostExecute(Boolean result) {
progressBar.setVisibility(View.GONE);
// If succeeded
if (result) {
populateRecyclerView();
// Show toast when data has been loaded for the first time
Toast.makeText(MainActivity.this, getString(R.string.json_toast_data_loaded), Toast.LENGTH_SHORT).show();
} else {
// If failed make toast
Toast.makeText(MainActivity.this, getString(R.string.json_toast_data_failed), Toast.LENGTH_SHORT).show();
}
}
}
/**
* Populates recyclerView and adds OnItemClickListener
*/
private void populateRecyclerView()
{
WallItem w = WallItemList.get(0);
adapter = new MyRecyclerViewAdapter(MainActivity.this, WallItemList);
mRecyclerView.setAdapter(adapter);
adapter.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(WallItem item) {
// Function to start new activity
Class detailActivity = DetailActivity.class;
// Create intent
Intent startDetailActivityIntent = new Intent(MainActivity.this, detailActivity);
// Add object to intent
startDetailActivityIntent.putExtra("detailWallItem", (Parcelable)item);
// Start activity
startActivity(startDetailActivityIntent);
}
});
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// Save instances of existing objects
outState.putString(JSON_KEY_RESULTS, JSONResults);
outState.putParcelableArrayList(WALL_ITEM_LIST_KEY, (ArrayList<? extends Parcelable>) this.WallItemList);
}
/**
* Parses JSON result
*
* #param result
*/
private void parseResult(String result) {
WallItemList = new ArrayList<>();
try {
JSONArray mJsonArray = new JSONArray(result);
// Loop through JSON array
for (int i = 0; i < mJsonArray.length(); i++) {
// Get picture URI fragment from JSON
String pictureURIFragment = mJsonArray.getJSONObject(i)
.getJSONArray("images").getJSONObject(0)
.getString("url");
// Load images into String
JSONArray JSONImageArray = mJsonArray.getJSONObject(i)
.getJSONArray("images");
// Create array for wallItem
String[] imageArray = new String[JSONImageArray.length()];
// Loop through JSONArray
for(int x = 0; x < JSONImageArray.length(); x++)
{
String pictureURLFragment = JSONImageArray.getJSONObject(x).getString("url");
// Built picture
URL pictureURL = NetworkUtils.builtPictureUrl(pictureURLFragment.toLowerCase());
imageArray[x] = java.net.URLDecoder.decode(pictureURL.toString());
}
// Built picture
URL pictureURL = NetworkUtils.builtPictureUrl(pictureURIFragment.toLowerCase());
String cleanPictureUrl = java.net.URLDecoder.decode(pictureURL.toString());
// add wall item to the list
WallItem item = new WallItem();
// Set fields of wallItem
item.setThumbnail(cleanPictureUrl);
item.setTitle(mJsonArray.getJSONObject(i).getString("author"));
item.setPhotographer(mJsonArray.getJSONObject(i).getString("photographer"));
item.setAddress(mJsonArray.getJSONObject(i).getString("address"));
item.setMaterial(mJsonArray.getJSONObject(i).getJSONObject("material").getString(langPreferenceString));
item.setDescription(mJsonArray.getJSONObject(i).getJSONObject("description").getString(langPreferenceString));
item.setImgURLArray(imageArray);
// Add wallItem to list
WallItemList.add(item);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId() == R.id.api_url_settings_item)
{
Intent startSettingsActivity = new Intent(this, SettingsActivity.class);
startActivity(startSettingsActivity);
return true;
}
return super.onOptionsItemSelected(item);
}
private void getDeviceLanguage()
{
Log.d("HERE", Locale.getDefault().getLanguage());
}
#Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if(key.equals(getString(R.string.pref_api_url_key)))
{
// Update String again
APIUrlPreferenceString = sharedPreferences.getString(getString(R.string.pref_api_url_key), getString(R.string.pref_api_url_def_value));
new DownloadTask().execute();
}
if(key.equals(getString(R.string.pref_lang_check_key)))
{
// 1. If true, use system language.
// 2. if System language != en or nl, use default language: en.
// 3. if false, make selectable
}
if(key.equals(getString(R.string.pref_lang_list_key)) || key.equals(getString(R.string.pref_lang_check_key)))
{
// Language settings
if(sharedPreferences.getBoolean(getString(R.string.pref_lang_check_key), true))
{
// Use device settings
setLanguageSettings(Resources.getSystem().getConfiguration().locale.getLanguage());
langPreferenceString = Resources.getSystem().getConfiguration().locale.getLanguage();
}
else
{
// Use preference settings
setLanguageSettings(sharedPreferences.getString(getString(R.string.pref_lang_list_key), getString(R.string.pref_lang_label_en)));
langPreferenceString = sharedPreferences.getString(getString(R.string.pref_lang_list_key), getString(R.string.pref_lang_label_en));
}
// Reload data after executing new Download task
new DownloadTask().execute();
this.recreate();
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
#Override
protected void onDestroy() {
super.onDestroy();
PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
}
}
Here is my MyRecyclerViewAdapter.java
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.CustomViewHolder> {
private List<WallItem> wallItemList;
private Context mContext;
private OnItemClickListener onItemClickListener;
public MyRecyclerViewAdapter(Context context, List<WallItem> wallItemList) {
this.wallItemList = wallItemList;
this.mContext = context;
WallItem w = wallItemList.get(0);
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, null);
CustomViewHolder viewHolder = new CustomViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(CustomViewHolder customViewHolder, int i) {
final WallItem wallItem = wallItemList.get(i);
//Download image using picasso library
if (!TextUtils.isEmpty(wallItem.getThumbnail())) {
// Load image into imageView
Picasso.with(mContext).load(wallItem.getThumbnail())
.error(R.drawable.placeholder)
.placeholder(R.drawable.placeholder)
.into(customViewHolder.imageView);
}
//Setting text view title
customViewHolder.textView.setText(Html.fromHtml(wallItem.getMaterial()));
// Set OnClickListener to wallItem
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
onItemClickListener.onItemClick(wallItem);
}
};
customViewHolder.imageView.setOnClickListener(listener);
customViewHolder.textView.setOnClickListener(listener);
}
// Overwrite to return
#Override
public int getItemCount() {
return (null != wallItemList ? wallItemList.size() : 0);
}
class CustomViewHolder extends RecyclerView.ViewHolder {
protected ImageView imageView;
protected TextView textView;
public CustomViewHolder(View view) {
super(view);
this.imageView = (ImageView) view.findViewById(R.id.thumbnail);
this.textView = (TextView) view.findViewById(R.id.title);
}
}
public OnItemClickListener getOnItemClickListener() {
return onItemClickListener;
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
}
My apologies for posting all the code but I can't identify the crucial points and don't have enough experience to pinpoint where it's going wrong. If anyone could help you would it would be greatly appreciated!
I suggest you to initialize and set the adapter in onCreate() method with an empty array of WallItems.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new MyRecyclerViewAdapter(MainActivity.this, new ArrayList<WallItem>());
mRecyclerView.setAdapter(adapter);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
// Setup shared preferences
setupSharedPreferences();
// Load the recyclerView
loadRecyclerView(savedInstanceState);
}
To update the list of items, I normally have a setItems method inside my adapter that updates the list and calls notifyDataSetChanged()
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.CustomViewHolder> {
...
public void setItems(List<WallItem> items) {
this.wallItemList = wallItemList;
notifyDataSetChanged();
}
}
Your populateRecyclerView method then should call the setItems method to update the new list of items.
private void populateRecyclerView()
{
WallItem w = WallItemList.get(0);
adapter.setItems(WallItemList);
adapter.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(WallItem item) {
// Function to start new activity
Class detailActivity = DetailActivity.class;
// Create intent
Intent startDetailActivityIntent = new Intent(MainActivity.this, detailActivity);
// Add object to intent
startDetailActivityIntent.putExtra("detailWallItem", (Parcelable)item);
// Start activity
startActivity(startDetailActivityIntent);
}
});
}
I didn't test, buy this is how I normally use RecyclerView.
I'm programming with android studio and I want to parse a json and put the details in my object in a function in MainActivity and I do it well in that function and every thing is ok! But when I want to use it in onCreate it's null.
What should I do?
MainActivity:
public class MainActivity extends ActionBarActivity {
ArrayList<Details> details= new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new myserver2().execute("");
Adapter adptor=new Adapter(this,details);
ListView l= (ListView) findViewById(R.id.listview);
l.setAdapter(adptor);
}
private class myserver2 extends AsyncTask<String,String,String> {
String s;
#Override
protected String doInBackground(String... params) {
HttpClient client = new DefaultHttpClient();
HttpGet hp = new HttpGet("http://jsonplaceholder.typicode.com/posts");
try
{
HttpResponse r = client.execute(hp);
HttpEntity ent = r.getEntity();
String s = EntityUtils.toString(ent);
JSONArray array = new JSONArray(s);
JSONObject obj = new JSONObject();
for(int i=0;i<array.length();i++){
Details d = new Details();
obj=array.getJSONObject(i);
d.setId(Integer.parseInt(obj.getString("id")));
d.setUserid(Integer.parseInt(obj.getString("userId")));
d.setBody(obj.getString("body"));
d.setTitle(obj.getString("title"));
Log.i("**(*", obj.getString("title"));
details.add(d);
}
Log.i("**(*", details.get(0).getTitle());
} catch (
IOException e
)
{
e.printStackTrace();
} catch (
JSONException e
)
{
e.printStackTrace();
}
return null;
}
}
Details:
public class Details {
int id=0,userid=0;
String body,title;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
My log after the for in myserver given the true title but if I had this Log in onCreate it throws an exception:
java.lang.IndexOutOfBoundsException
And it's because of my Arraylis is null in onCreate but why and what should I do,I dont know!
Your onCreates tries to access the arraylist while the asyc task is not finished. To mamke sure you set the adapter only after asyc task is finished, set the adapter inside onPostExecute()
#Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
if(details.size > 0){
Adapter adptor=new Adapter(this,details);
l.setAdapter(adptor);
}else{
l.setAdapter(null);
}
}
Hope that helps!
You can override the onPostExecute() method inside your AsyncTask and you can set the adapter there normally. Add this code inside myserver2 class
#Override
protected void onPostExecute(String message) {
super.onPostExecute(message);
Adapter adptor=new Adapter(MainActivity.this,details);
ListView l= (ListView) findViewById(R.id.listview);
l.setAdapter(adptor);
}
and remove those 3 lines from your onCreate().
you can do this in asynctask Onpost() method
because some time network operation take time to get date but
Adapter adptor=new Adapter(this,details);
l.setAdapter(adptor);
since onPostExecute-Method from AsyncTask is called within your main UI-Thread, you can initialize you listview and adapter in onPostExecute-Method.
onPostExecute(Result), invoked on the UI thread after the background
computation finishes. The result of the background computation is
passed to this step as a parameter.
http://developer.android.com/reference/android/os/AsyncTask.html
#Override
protected void onPostExecute(String message) {
super.onPostExecute(message);
Adapter adptor=new Adapter(MainActivity.this,details);
ListView l= (ListView) findViewById(R.id.listview);
l.setAdapter(adptor);
}
do this in your oncreate method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Adapter adptor=new Adapter(this,details);
ListView l= (ListView) findViewById(R.id.listview);
l.setAdapter(adptor);
new myserver2().execute("");
}
and add this method in your AsyncTask
#Override
protected void onPostExecute(String message) {
super.onPostExecute(message);
adpter.notifydatasetchanged()
}