I don't understand why the size is null. So the data is not loaded in the recyclerview.
I load the URLS from the Images from the my database and it should be shown into the recyclerview. I tested and I get the URL's but they are not added to the list.
SharedPreferences USERNAMEsp;
String USERNAME;
RecyclerView recyclerViewImageSlider;
List<ImageGetter> imageList = new ArrayList<>();
ImageAdapter imageAdapter;
ImageGetter imageGetter;
PullData pullData = new PullData(Profil.this);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profil);
USERNAMEsp = getSharedPreferences("DATAUSERNAME",MODE_PRIVATE);
USERNAME = USERNAMEsp.getString("DATAUSERNAME","");
pullData.getData(USERNAME, "3", new Pullcallback() {
#Override
public void getSingleData(String data) {
imageGetter = new ImageGetter(data);
imageList.add(imageGetter);
}
#Override
public void getMultipleData(String[] multipledatas) {
}
#Override
public void onError(String errormessage) {
}
});
recyclerViewImageSlider = findViewById(R.id.recyclerViewImages);
imageAdapter = new ImageAdapter(Profil.this, imageList, new AdapterCallback() {
#Override
public void onLoaded() {
}
});
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(Profil.this,LinearLayoutManager.HORIZONTAL,false);
recyclerViewImageSlider.setLayoutManager(layoutManager);
recyclerViewImageSlider.setHasFixedSize(true);
recyclerViewImageSlider.setAdapter(imageAdapter);
recyclerViewImageSlider.setOnFlingListener(new PagerSnapHelper());
SnapHelper snapHelper = new PagerSnapHelper();
snapHelper.attachToRecyclerView(recyclerViewImageSlider);
imageAdapter.notifyDataSetChanged();
}
Call imageAdapter.notifyDataSetChanged(); after imageList.add(imageGetter); because you are modifying arraylist and you have to let the adapter know to reload data set
pullData.getData(USERNAME, "3", new Pullcallback() {
#Override
public void getSingleData(String data) {
imageGetter = new ImageGetter(data);
imageList.add(imageGetter);
imageAdapter.notifyDataSetChanged();
}
#Override
public void getMultipleData(String[] multipledatas) {
}
#Override
public void onError(String errormessage) {
}
});
Related
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());
}
});
}
how to send spinner data by volley to database?
The codes are all sent and no problem Only Spinner field is not sent to the data table.
String[] Cat = {"املاک","وسایل نقلیه","لوازم الکترونیکی","مربوط به خانه","خدمات","وسایل شخصی","سرگرمی و فراغت","اجتماعی","برای کسب و کار","استخدام و کاریابی"};
String[] CatCode = {"1","2","3","4","5","6","7","8","9","10"};
String cate = "";
Send Data Class :
String name,description,phone,email,city;
String[] Cat = {"املاک","وسایل نقلیه","لوازم الکترونیکی","مربوط به خانه","خدمات","وسایل شخصی","سرگرمی و فراغت","اجتماعی","برای کسب و کار","استخدام و کاریابی"};
String[] CatCode = {"1","2","3","4","5","6","7","8","9","10"};
String cate = "";
StringRequest AddAdvReq;
private String Post_Url = "http://192.168.1.102/tablo/api/get_new_adv"
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_adv);
defineVolleyCodes();
defineViews();
defineClicks();
ArrayAdapter<String> catAdapter = new ArrayAdapter<>(getApplicationContext(),R.layout.spinner_row,Cat);
SpinCategory.setAdapter(catAdapter);
SpinCategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
cate = CatCode[position];
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
cate = CatCode[0];
}
});
}
//==========================
private void defineVolleyCodes() {
AddAdvReq = new StringRequest(Request.Method.POST, Post_Url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(AddAdv.this, response, Toast.LENGTH_SHORT).show();
finish();
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(AddAdv.this, error.toString(), Toast.LENGTH_SHORT).show();
}
}
)
{
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
//Add Post Parameters
String STRImage = getStringImage(bitmap);
params.put("name",name);
params.put("description",description);
params.put("phone",phone);
params.put("email",email);
params.put("city",city);
params.put("category_id",cate);
return params;
}
};
}
//==========================
private void defineViews() {
//===========================Define All EditTexts
ETxtName = (EditText)findViewById(R.id.etxt_name);
ETxtDescription = (EditText)findViewById(R.id.etxt_description);
ETxtPhone = (EditText)findViewById(R.id.etxt_phone);
ETxtEmail = (EditText)findViewById(R.id.etxt_email);
ETxtCity = (EditText)findViewById(R.id.etxt_city);
//==============================Define All Buttons
SpinCategory = (Spinner)findViewById(R.id.spin_category);
//==============================Define All Buttons
BtnAddAdv = (Button)findViewById(R.id.btn_add_adv);
}
//==========================
private void defineClicks() {
BtnAddAdv.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Load Fields
name = ETxtName.getText().toString();
description = ETxtDescription.getText().toString();
phone = ETxtPhone.getText().toString();
email = ETxtEmail.getText().toString();
city = ETxtCity.getText().toString();
cate = SpinCategory.getSelectedItem().toString();
//Add Request To Queue
AppController.getInstance().addToRequestQueue(AddAdvReq);
}
});
}
}
params.put("category_id",cate);
cate = SpinCategory.getSelectedItem().toString();
What's the problem?
Thanks for all.
You are storing the selected item in the variable here
SpinCategory.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
cate = CatCode[position];
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
cate = CatCode[0];
}
});
cate - use it.
In the click listener you override it with the new value from the spinner that may be invalid(I cannot tell you more because I don't see the whole code)
just delete this cate = SpinCategory.getSelectedItem().toString(); line from the BtnAddAdv click listener and try - maybe it will work
Hope it helps.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_adv);
defineVolleyCodes(); // Remove heare
defineViews();
defineClicks(); // Remove heare
ArrayAdapter<String> catAdapter = new ArrayAdapter<>(getApplicationContext(),R.layout.spinner_row,Cat);
SpinCategory.setAdapter(catAdapter);
SpinCategory.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent,
View view, int pos, long id) {
cate = parent.getItemAtPosition().toString();
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
});
defineVolleyCodes();
defineClicks();
}
please set this method call after the SpinCategory as above code mention.
Then in BtnAddAdv cate= cate; in your code.
I hope it'll help you...!
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.
.
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 loading json file from online and saving it on Sqlite such that when app is offline...Then still user will be able to see the data.
It works fine in MainActivity.
But when I try to covert it into fragment, I'm getting errors of Fragment cannot be cast in to FlowerAdapter$FlowerClickListener
Here is the error file
My Fragment name is nepali.
Here is the Mainactivity
public class MainActivity extends AppCompatActivity implements FlowerAdapter.FlowerClickListener, FlowerFetchListener {
private static final String TAG = MainActivity.class.getSimpleName();
private RecyclerView mRecyclerView;
private RestManager mManager;
private FlowerAdapter mFlowerAdapter;
private FlowerDatabase mDatabase;
private Button mReload;
private ProgressDialog mDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
configViews();
mManager = new RestManager();
mDatabase = new FlowerDatabase(this);
loadFlowerFeed();
mReload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loadFlowerFeed();
}
});
}
private void loadFlowerFeed() {
mDialog = new ProgressDialog(MainActivity.this);
mDialog.setMessage("Loading Flower Data...");
mDialog.setCancelable(true);
mDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mDialog.setIndeterminate(true);
mFlowerAdapter.reset();
mDialog.show();
if (getNetworkAvailability()) {
getFeed();
} else {
getFeedFromDatabase();
}
}
private void getFeedFromDatabase() {
mDatabase.fetchFlowers(this);
}
private void configViews() {
mReload = (Button) findViewById(R.id.reload);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false));
mFlowerAdapter = new FlowerAdapter(this);
mRecyclerView.setAdapter(mFlowerAdapter);
}
#Override
public void onClick(int position) {
}
public void getFeed() {
Call<List<Flower>> listCall = mManager.getFlowerService().getAllFlowers();
listCall.enqueue(new Callback<List<Flower>>() {
#Override
public void onResponse(Call<List<Flower>> call, Response<List<Flower>> response) {
if (response.isSuccessful()) {
List<Flower> flowerList = response.body();
for (int i = 0; i < flowerList.size(); i++) {
Flower flower = flowerList.get(i);
SaveIntoDatabase task = new SaveIntoDatabase();
task.execute(flower);
mFlowerAdapter.addFlower(flower);
}
} else {
int sc = response.code();
switch (sc) {
case 400:
Log.e("Error 400", "Bad Request");
break;
case 404:
Log.e("Error 404", "Not Found");
break;
default:
Log.e("Error", "Generic Error");
}
}
mDialog.dismiss();
}
#Override
public void onFailure(Call<List<Flower>> call, Throwable t) {
mDialog.dismiss();
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public boolean getNetworkAvailability() {
return Utils.isNetworkAvailable(getApplicationContext());
}
#Override
public void onDeliverAllFlowers(List<Flower> flowers) {
}
#Override
public void onDeliverFlower(Flower flower) {
mFlowerAdapter.addFlower(flower);
}
#Override
public void onHideDialog() {
mDialog.dismiss();
}
public class SaveIntoDatabase extends AsyncTask<Flower, Void, Void> {
private final String TAG = SaveIntoDatabase.class.getSimpleName();
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Flower... params) {
Flower flower = params[0];
try {
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
return null;
}
}
}
and FlowerDatabase class is
public class FlowerDatabase extends SQLiteOpenHelper {
private static final String TAG = FlowerDatabase.class.getSimpleName();
public FlowerDatabase(Context context) {
super(context, Constants.DATABASE.DB_NAME, null, Constants.DATABASE.DB_VERSION);
}
#Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL(Constants.DATABASE.CREATE_TABLE_QUERY);
} catch (SQLException ex) {
Log.d(TAG, ex.getMessage());
}
}
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(Constants.DATABASE.DROP_QUERY);
this.onCreate(db);
}
public void addFlower(Flower flower) {
Log.d(TAG, "Values Got " + flower.getName());
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(Constants.DATABASE.PRODUCT_ID, flower.getProductId());
values.put(Constants.DATABASE.CATEGORY, flower.getCategory());
values.put(Constants.DATABASE.PRICE, Double.toString(flower.getPrice()));
values.put(Constants.DATABASE.INSTRUCTIONS, flower.getInstructions());
values.put(Constants.DATABASE.NAME, flower.getName());
try {
db.insert(Constants.DATABASE.TABLE_NAME, null, values);
} catch (Exception e) {
}
db.close();
}
public void fetchFlowers(FlowerFetchListener listener) {
FlowerFetcher fetcher = new FlowerFetcher(listener, this.getWritableDatabase());
fetcher.start();
}
public class FlowerFetcher extends Thread {
private final FlowerFetchListener mListener;
private final SQLiteDatabase mDb;
public FlowerFetcher(FlowerFetchListener listener, SQLiteDatabase db) {
mListener = listener;
mDb = db;
}
#Override
public void run() {
Cursor cursor = mDb.rawQuery(Constants.DATABASE.GET_FLOWERS_QUERY, null);
final List<Flower> flowerList = new ArrayList<>();
if (cursor.getCount() > 0) {
if (cursor.moveToFirst()) {
do {
Flower flower = new Flower();
flower.setFromDatabase(true);
flower.setName(cursor.getString(cursor.getColumnIndex(Constants.DATABASE.NAME)));
flower.setPrice(Double.parseDouble(cursor.getString(cursor.getColumnIndex(Constants.DATABASE.PRICE))));
flower.setInstructions(cursor.getString(cursor.getColumnIndex(Constants.DATABASE.INSTRUCTIONS)));
flower.setCategory(cursor.getString(cursor.getColumnIndex(Constants.DATABASE.CATEGORY)));
flower.setProductId(Integer.parseInt(cursor.getString(cursor.getColumnIndex(Constants.DATABASE.PRODUCT_ID))));
flowerList.add(flower);
publishFlower(flower);
} while (cursor.moveToNext());
}
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
mListener.onDeliverAllFlowers(flowerList);
mListener.onHideDialog();
}
});
}
public void publishFlower(final Flower flower) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
#Override
public void run() {
mListener.onDeliverFlower(flower);
}
});
}
}
}
and FlowerAdapter Class is
public class FlowerAdapter extends RecyclerView.Adapter<FlowerAdapter.Holder> {
private static final String TAG = FlowerAdapter.class.getSimpleName();
private final FlowerClickListener mListener;
private List<Flower> mFlowers;
public FlowerAdapter(FlowerClickListener listener) {
mFlowers = new ArrayList<>();
mListener = listener;
}
#Override
public Holder onCreateViewHolder(ViewGroup parent, int viewType) {
View row = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_item, null, false);
return new Holder(row);
}
#Override
public void onBindViewHolder(Holder holder, int position) {
Flower currFlower = mFlowers.get(position);
holder.mName.setText(currFlower.getName());
holder.minstruction.setText(currFlower.getInstructions());
}
#Override
public int getItemCount() {
return mFlowers.size();
}
public void addFlower(Flower flower) {
mFlowers.add(flower);
notifyDataSetChanged();
}
/**
* #param position
* #return
*/
public Flower getSelectedFlower(int position) {
return mFlowers.get(position);
}
public void reset() {
mFlowers.clear();
notifyDataSetChanged();
}
public class Holder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView mName, minstruction;
public Holder(View itemView) {
super(itemView);
mName = (TextView) itemView.findViewById(R.id.flowerName);
minstruction = (TextView) itemView.findViewById(R.id.flowerPrice);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
mListener.onClick(getLayoutPosition());
}
}
public interface FlowerClickListener {
void onClick(int position);
}
}
My fragment class is that I try to convert above Mainactivity code into Frament class is
public class nepali extends Fragment {
private static final String TAG = nepali.class.getSimpleName();
private RecyclerView mRecyclerView;
private RestManager mManager;
private FlowerAdapter mFlowerAdapter;
private FlowerDatabase mDatabase;
private Button mReload;
private ProgressDialog mDialog;
View view;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_data, container, false);
configViews();
mManager = new RestManager();
mDatabase = new FlowerDatabase(getActivity());
loadFlowerFeed();
mReload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
loadFlowerFeed();
}
});
return view;
}
private void loadFlowerFeed() {
mDialog = new ProgressDialog(getActivity());
mDialog.setMessage("Loading Flower Data...");
mDialog.setCancelable(true);
mDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mDialog.setIndeterminate(true);
mFlowerAdapter.reset();
mDialog.show();
if (getNetworkAvailability()) {
getFeed();
} else {
getFeedFromDatabase();
}
}
private void getFeedFromDatabase() {
mDatabase.fetchFlowers(this);
}
private void configViews() {
mReload = (Button) view.findViewById(R.id.reload);
mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
mFlowerAdapter = new FlowerAdapter((FlowerAdapter.FlowerClickListener) this);;
mRecyclerView.setAdapter(mFlowerAdapter);
}
public void getFeed() {
Call<List<Flower>> listCall = mManager.getFlowerService().getAllFlowers();
listCall.enqueue(new Callback<List<Flower>>() {
#Override
public void onResponse(Call<List<Flower>> call, Response<List<Flower>> response) {
if (response.isSuccessful()) {
List<Flower> flowerList = response.body();
for (int i = 0; i < flowerList.size(); i++) {
Flower flower = flowerList.get(i);
SaveIntoDatabase task = new SaveIntoDatabase();
task.execute(flower);
mFlowerAdapter.addFlower(flower);
}
} else {
int sc = response.code();
switch (sc) {
case 400:
Log.e("Error 400", "Bad Request");
break;
case 404:
Log.e("Error 404", "Not Found");
break;
default:
Log.e("Error", "Generic Error");
}
}
mDialog.dismiss();
}
#Override
public void onFailure(Call<List<Flower>> call, Throwable t) {
mDialog.dismiss();
Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public boolean getNetworkAvailability() {
return Utils.isNetworkAvailable(getActivity());
}
public void onDeliverFlower(Flower flower) {
mFlowerAdapter.addFlower(flower);
}
public void onHideDialog() {
mDialog.dismiss();
}
public class SaveIntoDatabase extends AsyncTask<Flower, Void, Void> {
private final String TAG = SaveIntoDatabase.class.getSimpleName();
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Flower... params) {
Flower flower = params[0];
try {
} catch (Exception e) {
Log.d(TAG, e.getMessage());
}
return null;
}
}
}
Lastly the FlowerService class is
public interface FlowerService {
#GET("/routine/first.json")
Call<List<Flower>> getAllFlowers();
}
and FlowerFetchListener Class is
public interface FlowerFetchListener {
void onDeliverAllFlowers(List<Flower> flowers);
void onDeliverFlower(Flower flower);
void onHideDialog();
}
Please Help....and Thanks in advance.
You should not call db and network from activity or fragment. Try to learn MVVM architecture and use ViewModel to store the data from db or network. You may put a lot of effort making your app work but it will still lead to crashes (especially after you introduce fragment and call db and API from there). You will need to handle your data state during configuration changes. Listen to this talk and start writing clean code https://m.youtube.com/watch?v=5qlIPTDE274
The error you get is because you pass wrong parameter into adapter constructor ‘new FlowerAdapter((FlowerAdapter.FlowerClickListener) this)’. If you want to pass a listener to the adapter you need to pass the class which implements the listener: either activity - then pass getActivity(), or fragment ‘this’ - then make fragment implement implements FlowerAdapter.FlowerClickListener.Be aware that it can be null when fragment is not attached to activity, eg configuration change.