I am trying to retrieve selectedItems from a lispicker in multiSelection mode. Data appears in FullModelItemTemplate but when I select items, I am unable to get the values. Here is my ListPicker XAML
<toolkit:ListPicker x:Name="location" ItemsSource="{Binding Items,Mode=TwoWay}" ItemTemplate="{StaticResource DataTemplate2}" FullModeItemTemplate="{StaticResource DataTemplate3}" HeaderTemplate="{StaticResource header}" SelectionMode="Multiple" SelectedItems="{Binding SelectedItem,Mode=TwoWay}" >
MainViewModel
public class MainViewModel : ViewModelBase, INotifyPropertyChanged
{
public ObservableCollection<ItemViewModel> Items { get; private set; }
public MainViewModel()
{
Items = new ObservableCollection<ItemViewModel>();
LoadData();
}
public const string SelectedItemPropertyName = "SelectedItem";
private ObservableCollection<ItemViewModel> selectedItem;
public ObservableCollection<ItemViewModel> SelectedItem
{
get
{
return selectedItem;
}
set
{
if (value != selectedItem)
{
selectedItem = value;
NotifyPropertyChanged(SelectedItemPropertyName);
}
}
}
public void LoadData()
{
// Sample data; replace with real data
this.Items.Add(new ItemViewModel() { ID = "0", Cuisine = "Thai", CuisineImg = "Assets/Images/thsi.png", Location = "Shantinagar" });
this.Items.Add(new ItemViewModel() { ID = "1", Cuisine = "Indian", CuisineImg = "Assets/Images/indian.png", Location = "Mirpur" });
this.Items.Add(new ItemViewModel() { ID = "2", Cuisine = "Chinese", CuisineImg = "Assets/Images/chinese.png", Location = "Dhanmondi" });
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
ItemViewModel
public class ItemViewModel : INotifyPropertyChanged
{
private string _id;
public string ID
{
get
{
return _id;
}
set
{
if (value != _id)
{
_id = value;
NotifyPropertyChanged("ID");
}
}
}
private string _location;
public string Location
{
get
{
return _location;
}
set
{
if (value != _location)
{
_location = value;
NotifyPropertyChanged("Location");
}
}
}
private string _cuisine;
public string Cuisine
{
get
{
return _cuisine;
}
set
{
if (value != _cuisine)
{
_cuisine = value;
NotifyPropertyChanged("Cuisine");
}
}
}
private string _cuisineImg;
public string CuisineImg
{
get
{
return _cuisineImg;
}
set
{
if (value != _cuisineImg)
{
_cuisineImg = value;
NotifyPropertyChanged("CuisineImg");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Note that I am using MVVM light and if the selectionMode is single I face no problems fetching the selected value but multipleSelection mode is causing trouble
Related
I have created a custom jmsListenerContainerFactory and MessageListenerContainer for batch processing. The problem is when I pass my custom container factory in #JmsListener(containerFactory=" customContainerFactoryq1") in the listener file, whatever components that I am autowiring in the class is null. But works fine when
I use containerFactory of type DefaultJmsListenerContainerFactory inside the #JmsListener
annotation
Config class
#EnableJms
#Configuration
public class SpringBatchJmsConfig {
#Bean
public ActiveMQConnectionFactory receiverActiveMQConnectionFactory() {
ActiveMQConnectionFactory activeMQConnectionFactory =
new ActiveMQConnectionFactory();
activeMQConnectionFactory.setBrokerURL("tcp://localhost:61616");
return activeMQConnectionFactory;
}
#Bean(name="customContainerFactoryq1")
public CustomJmsListenerContainerFactory customJmsListenerContainerFactory() {
CustomJmsListenerContainerFactory factory = new CustomJmsListenerContainerFactory();
factory.setConnectionFactory(receiverActiveMQConnectionFactory());
return factory;
}
#Bean(name="defaultContainerFactoryq1")
public DefaultJmsListenerContainerFactory defaultJmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(receiverActiveMQConnectionFactory());
return factory;
}
#Bean(name="myCustomJmsTemplateMq1")
public JmsTemplate customJmsTemplateMq1() {
JmsTemplate jmsTemplate = new JmsTemplate();
jmsTemplate.setConnectionFactory(receiverActiveMQConnectionFactory());
return jmsTemplate;
}
Container
public static final int DEFAULT_BATCH_SIZE = 20;
private int batchSize = DEFAULT_BATCH_SIZE;
public CustomJmsListenerContainer() {i
super();
setSessionTransacted(true);
}
public int getBatchSize() {
return batchSize;
}
public void setBatchSize(int batchSize) {
this.batchSize = batchSize;
}
#Override
protected boolean doReceiveAndExecute(Object invoker, Session session, MessageConsumer consumer, TransactionStatus status) throws JMSException {
Connection conToClose = null;
MessageConsumer consumerToClose = null;
Session sessionToClose = null;
try {
Session sessionToUse = session;
MessageConsumer consumerToUse = consumer;
if (sessionToUse == null) {
Connection conToUse = null;
if (sharedConnectionEnabled()) {
conToUse = getSharedConnection();
} else {
conToUse = createConnection();
conToClose = conToUse;
conToUse.start();
}
sessionToUse = createSession(conToUse);
sessionToClose = sessionToUse;
}
if (consumerToUse == null) {
consumerToUse = createListenerConsumer(sessionToUse);
consumerToClose = consumerToUse;
}
List<Message> messages = new ArrayList<Message>();
int count = 0;
Message message = null;
do {
message = receiveMessage(consumerToUse);
if (message != null) {
messages.add(message);
}
}
while ((message != null) && (++count < batchSize));
if (messages.size() > 0) {
try {
doExecuteListener(sessionToUse, messages);
sessionToUse.commit();
} catch (Throwable ex) {
handleListenerException(ex);
if (ex instanceof JMSException) {
throw (JMSException) ex;
}
}
return true;
}
noMessageReceived(invoker, sessionToUse);
return false;
} finally {
JmsUtils.closeMessageConsumer(consumerToClose);
JmsUtils.closeSession(sessionToClose);
ConnectionFactoryUtils.releaseConnection(conToClose, getConnectionFactory(), true);
}
}
protected void doExecuteListener(Session session, List<Message> messages) throws JMSException {
System.out.println("Message Size inside container:" + messages.size());
if (!isAcceptMessagesWhileStopping() && !isRunning()) {
if (logger.isWarnEnabled()) {
logger.warn("Rejecting received messages because of the listener container "
+ "having been stopped in the meantime: " + messages);
}
rollbackIfNecessary(session);
throw new JMSException("Rejecting received messages as listener container is stopping");
}
MessagingMessageListenerAdapter container = (MessagingMessageListenerAdapter)getMessageListener();
Method method = null;
String method Name = null;
try {
method = container.getClass().getDeclaredMethod("getHandlerMethod");
method.setAccessible(true);
InvocableHandlerMethod methodNameObject = (InvocableHandlerMethod)method.invoke(container);
methodName = methodNameObject.getMethod().getName();
Class.forName("com.demo.jms.SampleListener").getMethod(methodName, List.class)invoke(Class.forName("com.demo.jms.SampleListener").newInstance(), message);
} catch (JMSException ex) {
rollbackOnExceptionIfNecessary(session, ex);
throw ex;
} catch (RuntimeException ex) {
rollbackOnExceptionIfNecessary(session, ex);
throw ex;
} catch (Error err) {
rollbackOnExceptionIfNecessary(session, err);
throw err;
}
}
#Override
protected void validateConfiguration() {
if (batchSize <= 0) {
throw new IllegalArgumentException("Property batchSize must be a value greater than 0");
}
}
public void setSessionTransacted(boolean transacted) {
if (!transacted) {
throw new IllegalArgumentException("Batch Listener requires a transacted Session");
}
super.setSessionTransacted(transacted);
}
}
Container Factory
#Nullable
private Executor taskExecutor;
#Nullable
private PlatformTransactionManager transactionManager;
#Nullable
private Integer cacheLevel;
#Nullable
private String cacheLevelName;
#Nullable
private String concurrency;
#Nullable
private Integer maxMessagesPerTask;
#Nullable
private Long receiveTimeout;
#Nullable
private Long recoveryInterval;
#Nullable
private BackOff backOff;
public CustomJmsListenerContainerFactory() {
}
public void setTaskExecutor(Executor taskExecutor) {
this.taskExecutor = taskExecutor;
}
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public void setCacheLevel(Integer cacheLevel) {
this.cacheLevel = cacheLevel;
}
public void setCacheLevelName(String cacheLevelName) {
this.cacheLevelName = cacheLevelName;
}
public void setConcurrency(String concurrency) {
this.concurrency = concurrency;
}
public void setMaxMessagesPerTask(Integer maxMessagesPerTask) {
this.maxMessagesPerTask = maxMessagesPerTask;
}
public void setReceiveTimeout(Long receiveTimeout) {
this.receiveTimeout = receiveTimeout;
}
public void setRecoveryInterval(Long recoveryInterval) {
this.recoveryInterval = recoveryInterval;
}
public void setBackOff(BackOff backOff) {
this.backOff = backOff;
}
protected CustomJmsListenerContainer createContainerInstance() {
CustomJmsListenerContainer container =new CustomJmsListenerContainer();
container.setBatchSize(60);
container.setCacheLevel(CustomJmsListenerContainer.CACHE_CONSUMER);
container.setConcurrentConsumers(1);
container.setMaxConcurrentConsumers(1);
return container;
}
protected void initializeContainer(CustomJmsListenerContainer container) {
if (this.taskExecutor != null) {
container.setTaskExecutor(this.taskExecutor);
}
if (this.transactionManager != null) {
container.setTransactionManager(this.transactionManager);
}
if (this.cacheLevel != null) {
container.setCacheLevel(this.cacheLevel);
} else if (this.cacheLevelName != null) {
container.setCacheLevelName(this.cacheLevelName);
}
if (this.concurrency != null) {
container.setConcurrency(this.concurrency);
}
if (this.maxMessagesPerTask != null) {
container.setMaxMessagesPerTask(this.maxMessagesPerTask);
}
if (this.receiveTimeout != null) {
container.setReceiveTimeout(this.receiveTimeout);
}
if (this.backOff != null) {
container.setBackOff(this.backOff);
if (this.recoveryInterval != null) {
this.logger.info("Ignoring recovery interval in DefaultJmsListenerContainerFactory in favor of BackOff");
}
} else if (this.recoveryInterval != null) {
container.setRecoveryInterval(this.recoveryInterval);
}
}
}
Listener
#Component
public class Sample Listener {
#Autowired
#Qualifier("myCustomJmsTemplateMq1")
private JmsTemplate jmsTemplate;
#JmsListener(containerFactory="customContainerFactoryq1", destination="myQueue")
public void getMessages(List<Message> msgs) {
//some logic
}
}
Can someone please help me on this.
All looks good to me; exactly what do you think is wrong?
I am using MVVM light. Initially I add two items; after that I am adding two more new items in the list, and calling the RaisePropertyChanged event; but it's not updating the list view, it's showing old items only. What is the problem in my code?
My Model
public class ViewPeopleModel
{
public event PropertyChangedEventHandler PropertyChanged;
private string _imageURL;
public string ImageURL
{
get
{
return _imageURL;
}
set
{
_imageURL = value;
OnPropertyChanged("ImageURL");
}
}
public void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
View Model
public class ViewPeopleViewModel : ViewModelBase
{
public ObservableCollection<ViewPeopleModel> ProfileList { get; set; }
public ViewPeopleViewModel()
{
ObservableCollection<ViewPeopleModel> _people = new ObservableCollection<ViewPeopleModel>();
_people.Add(new ViewPeopleModel { ImageURL = "url1" });
_people.Add(new ViewPeopleModel { ImageURL = "url2" });
ProfileList = _people;
RaisePropertyChanged("ProfileList");
}
public void AddNewPeople()
{
ObservableCollection<ViewPeopleModel> _people = new ObservableCollection<ViewPeopleModel>();
_people.Add(new ViewPeopleModel { ImageURL = "url5" });
_people.Add(new ViewPeopleModel { ImageURL = "url6" });
ProfileList = _people;
RaisePropertyChanged("ProfileList");
}
}
Try doing this in your AddNewPeople method
public void AddNewPeople()
{
ProfileList.Clear();
ProfileList.Add(new ViewPeopleModel{ ImageURL ="url5" });
ProfileList.Add(new ViewPeopleModel{ ImageURL ="url6" });
}
Has anyone integrated Google Place Autocomplete using Xamarin.Forms? I am to use it on a map for location suggestions. I've only seen resources for Xamarin.Android and Xamarin.iOS but on the part of implementing the AutoCompleteView, that I also don't know. I would be very thankful if someone could guide me with this. Thank you!
Place autocomplete can be implemented by using the Google Place API, whenever user enter a character, matching location with the entered character will be fetched from the Google server and binding back in User Interface.
Here's the link how to use Google Map Place API in Xamarin form:
http://www.appliedcodelog.com/2015/05/google-place-api-with-autocomplete-in.html
Also, please read the Official Google Places API Web Service:
https://developers.google.com/places/web-service/autocomplete
For iOS
[assembly: ExportRenderer(typeof(CustomAutoCompleteLocation), typeof(CustomAutoCompleteRenderer))]
namespace Aesthetic.iOS.Renderer
{
public class CustomAutoCompleteProfileRenderer : EntryRenderer
{
IntPtr inptr;
string tx = "1";
CustomAutoCompleteLocation _view;
Place place;
UITextField textView;
public UIWindow Window
{
get;
set;
}
protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
{
base.OnElementChanged(e);
_view = (CustomAutoCompleteLocation)Element;
if (Control != null)
{
textView = (UITextField)Control;
textView.Font = UIFont.FromName("Lato-Light", textView.Font.PointSize);
textView.BorderStyle = UITextBorderStyle.Line;
textView.Layer.BorderWidth = 1f;
textView.Layer.CornerRadius = 0f;
// do whatever you want to the textField here!
UIView paddingView = new UIView(new RectangleF(10, 16, 10, 16));
textView.LeftView = paddingView;
textView.LeftViewMode = UITextFieldViewMode.Always;
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var x = sender as CustomAutoComplete;
if (e.PropertyName == "IsFocused")
{
if (tx == "1")
{
Device.BeginInvokeOnMainThread(() =>
{
Window = new UIWindow(UIScreen.MainScreen.Bounds);
var controller = new LocationViewController();
Window.RootViewController = controller;
// make the window visible
Window.MakeKeyAndVisible();
controller.PlaceSelected1 += HandlePlaceSelection;
});
tx = "2";
}
else if (tx == "2") tx = "3";
else if (tx == "3") tx = "4";
else if (tx == "4") tx = "1";
}
}
private void HandlePlaceSelection(object sender, string locationData)
{
textView.Text = locationData;
Window.Hidden = true;
}
}
}
And this is location view controller
public partial class LocationViewController : UIViewController
{
public delegate void PlaceSelected(object sender, string locationData);
UITextField txtLocation;
public UIView backgroundView;
// UITextView txtLocation;
UIImageView googleAttribution;
UITableView tableViewLocationAutoComplete;
public event PlaceSelected PlaceSelected1;
public string strSampleString { get; set; }
LocationPredictionClass objAutoCompleteLocationClass;
string strAutoCompleteQuery;
LocationAutoCompleteTableSource objLocationAutoCompleteTableSource;
public LocationViewController() : base()
{
}
public override void ViewDidLoad()
{
base.ViewDidLoad();
FnInitializeView();
FnClickEventInit();
}
void FnInitializeView()
{
backgroundView = new UIView(View.Frame);
backgroundView.BackgroundColor = UIColor.White;
View.AddSubview(backgroundView);
txtLocation = new UITextField();
txtLocation.Frame = new CoreGraphics.CGRect(20, 20, View.Frame.Width-20, 45.0f);
txtLocation.TranslatesAutoresizingMaskIntoConstraints = false;
txtLocation.ReturnKeyType = UIReturnKeyType.Done;
txtLocation.BackgroundColor = UIColor.FromRGB(221,221,221);
txtLocation.TextColor = UIColor.Black;
View.AddSubview(txtLocation);
txtLocation.BecomeFirstResponder();
tableViewLocationAutoComplete = new UITableView();
tableViewLocationAutoComplete.Frame = new CoreGraphics.CGRect(txtLocation.Frame.X, txtLocation.Frame.Height+ txtLocation.Frame.Y, View.Frame.Width, View.Frame.Height - txtLocation.Frame.Height - txtLocation.Frame.Y);
tableViewLocationAutoComplete.BackgroundColor = UIColor.White;
tableViewLocationAutoComplete.Source = objLocationAutoCompleteTableSource;
View.AddSubview(tableViewLocationAutoComplete);
tableViewLocationAutoComplete.Hidden = false;
txtLocation.ShouldReturn += (textField) => textField.ResignFirstResponder();
StringBuilder builderLocationAutoComplete = new StringBuilder(Constants.strPlacesAutofillUrl);
builderLocationAutoComplete.Append("?input={0}").Append("&key=").Append(Constants.strGooglePlaceAPILey);
strAutoCompleteQuery = builderLocationAutoComplete.ToString();
builderLocationAutoComplete.Clear();
builderLocationAutoComplete = null;
}
void FnClickEventInit()
{
txtLocation.EditingChanged += async delegate (object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(txtLocation.Text))
{
tableViewLocationAutoComplete.Hidden = true;
}
else
{
if (txtLocation.Text.Length > 2)
{
//Autofill
string strFullURL = string.Format(strAutoCompleteQuery, txtLocation.Text);
objAutoCompleteLocationClass = await RestRequestClass.LocationAutoComplete(strFullURL);
if (objAutoCompleteLocationClass != null && objAutoCompleteLocationClass.status == "OK")
{
if (objAutoCompleteLocationClass.predictions.Count > 0)
{
if (objLocationAutoCompleteTableSource != null)
{
objLocationAutoCompleteTableSource.LocationRowSelectedEventAction -= LocationSelectedFromAutoFill;
objLocationAutoCompleteTableSource = null;
}
tableViewLocationAutoComplete.Hidden = false;
objLocationAutoCompleteTableSource = new LocationAutoCompleteTableSource(objAutoCompleteLocationClass.predictions);
objLocationAutoCompleteTableSource.LocationRowSelectedEventAction += LocationSelectedFromAutoFill;
tableViewLocationAutoComplete.Source = objLocationAutoCompleteTableSource;
tableViewLocationAutoComplete.ReloadData();
}
else
tableViewLocationAutoComplete.Hidden = true;
}
else
{
tableViewLocationAutoComplete.Hidden = true;
}
}
}
};
}
void LocationSelectedFromAutoFill(Prediction objPrediction)
{
DismissViewController(true, null);
Console.WriteLine(objPrediction.description);
PlaceSelected1(this, objPrediction.description);
txtLocation.ResignFirstResponder();
}
}
public class RestRequestClass
{
static async Task<string> CallService(string strURL)
{
WebClient client = new WebClient();
string strResult;
try
{
strResult = await client.DownloadStringTaskAsync(new Uri(strURL));
}
catch
{
strResult = "Exception";
}
finally
{
client.Dispose();
client = null;
}
return strResult;
}
internal static async Task<LocationPredictionClass> LocationAutoComplete(string strFullURL)
{
LocationPredictionClass objLocationPredictClass = null;
LocationPredictionClass objLocationPredictClass12 = new LocationPredictionClass();
objLocationPredictClass12.predictions = new List<Prediction>();
string strResult = await CallService(strFullURL);
if (strResult != "Exception")
{
objLocationPredictClass = JsonConvert.DeserializeObject<LocationPredictionClass>(strResult);
}
foreach (Prediction objPred in objLocationPredictClass.predictions)
{
if (objPred.types[0] == "country")
{
objLocationPredictClass12.predictions.Add(objPred);
objLocationPredictClass12.status = "OK";
}
}
// string[] strPredictiveText = new string[data.Count];
//int index = 0;
// foreach (Prediction objPred in data)
// {
// strPredictiveText[index] = objPred.description;
// index++;
// }
return objLocationPredictClass12;
}
}
public class MatchedSubstring
{
public int length { get; set; }
public int offset { get; set; }
}
public class Term
{
public int offset { get; set; }
public string value { get; set; }
}
public class Prediction
{
public string description { get; set; }
public string id { get; set; }
public List<MatchedSubstring> matched_substrings { get; set; }
public string place_id { get; set; }
public string reference { get; set; }
public List<Term> terms { get; set; }
public List<string> types { get; set; }
}
public class LocationPredictionClass
{
public List<Prediction> predictions { get; set; }
public string status { get; set; }
}
public class Constants
{
public static string strGooglePlaceAPILey = "AIzaSyBXJntNIs2aAvKIRwrgCEwOGwnigbSWep8";
public static string strPlacesAutofillUrl = "https://maps.googleapis.com/maps/api/place/autocomplete/json";
}
public class LocationAutoCompleteTableSource : UITableViewSource
{
const string strCellIdentifier = "Cell";
readonly List<Prediction> lstLocations;
internal event Action<Prediction> LocationRowSelectedEventAction;
public LocationAutoCompleteTableSource(List<Prediction> arrItems)
{
lstLocations = arrItems;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return lstLocations.Count;
}
public override UIView GetViewForFooter(UITableView tableView, nint section)
{
return new UIView();
}
public override UITableViewCell GetCell(UITableView tableView, Foundation.NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(strCellIdentifier) ?? new UITableViewCell(UITableViewCellStyle.Default, strCellIdentifier);
cell.TextLabel.Text = lstLocations[indexPath.Row].description;
cell.TextLabel.Font = UIFont.SystemFontOfSize(12);
return cell;
}
public override void RowSelected(UITableView tableView, Foundation.NSIndexPath indexPath)
{
if (LocationRowSelectedEventAction != null)
{
LocationRowSelectedEventAction(lstLocations[indexPath.Row]);
}
tableView.DeselectRow(indexPath, true);
}
}
}
I have implemented recyclerview in my application and now i need to fetch data from the server and i just came to know about volley being the best way to fetch data. I searched online but i am unable to find a proper tutorial for the same.
This is how i initialized the recyclerview in my code.(which has hardcoded data set)
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(linearLayoutManager);
mAdapter = new CardAdapter();
mRecyclerView.setAdapter(mAdapter);
here is the adapter code.
public class CardAdapter extends RecyclerView.Adapter<CardAdapter.ViewHolder> {
ArrayList<BusRouteNameDetails> mItems;
public int TAG=0;
public CardAdapter() {
super();
mItems = new ArrayList<>();
BusRouteNameDetails routename = new BusRouteNameDetails();
routename.setName("xyz");
routename.setNumber("X4");
mItems.add(routename);
routename = new BusRouteNameDetails();
routename.setName("xyz");
routename.setNumber("X4");
mItems.add(routename);
routename = new BusRouteNameDetails();
routename.setName("xyz");
routename.setNumber("X4");
mItems.add(routename);
routename = new BusRouteNameDetails();
routename.setName("xyz");
routename.setNumber("X4");
mItems.add(routename);
routename = new BusRouteNameDetails();
routename.setName("xyz");
routename.setNumber("X4");
mItems.add(routename);
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.busroutename_list, viewGroup, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int i) {
BusRouteNameDetails routename = mItems.get(i);
viewHolder.tvName.setText(routename.getName());
viewHolder.tvRoutename.setText(routename.getNumber());
Log.e("TAG","i value="+ i);
if(i==mItems.size()-1)
viewHolder.seperator.setVisibility(View.INVISIBLE);
}
#Override
public int getItemCount() {
Log.e("TAG","item size"+ mItems.size());
return mItems.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
public TextView tvName;
public TextView tvRoutename;
public View seperator;
public ViewHolder(View itemView) {
super(itemView);
tvName = (TextView)itemView.findViewById(R.id.RouteName1);
tvRoutename = (TextView)itemView.findViewById(R.id.Route_src_dest);
seperator=(View)itemView.findViewById(R.id.seperator);
}
}
}
And here are the getters and setters
public class BusRouteNameDetails {
private String mName;
private String mNumber;
public String getName() {
return mName;
}
public void setName(String name) {
this.mName = name;
}
public String getNumber() {
return mNumber;
}
public void setNumber(String Number) {
this.mNumber = Number;
}
}
You can try as my following solution:
Let's assume the server response as the following JSON:
[
{
"name": "Person 1",
"age": 30
},
{
"name": "Person 2",
"age": 20
},
{
"name": "Person 3",
"age": 40
}
]
In your Android project:
public class Person {
String name;
Integer age;
Person() {
}
}
public class RVAdapter extends RecyclerView.Adapter<RVAdapter.PersonViewHolder> {
List<Person> persons;
RVAdapter(List<Person> persons) {
this.persons = persons;
}
#Override
public PersonViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview, parent, false);
PersonViewHolder pvh = new PersonViewHolder(v);
return pvh;
}
#Override
public void onBindViewHolder(PersonViewHolder holder, int position) {
holder.personName.setText(persons.get(position).name);
holder.personAge.setText(String.valueOf(persons.get(position).age));
}
#Override
public int getItemCount() {
if (persons != null) {
return persons.size();
}
return 0;
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
public static class PersonViewHolder extends RecyclerView.ViewHolder {
CardView cv;
TextView personName;
TextView personAge;
PersonViewHolder(View itemView) {
super(itemView);
cv = (CardView) itemView.findViewById(R.id.cv);
personName = (TextView) itemView.findViewById(R.id.person_name);
personAge = (TextView) itemView.findViewById(R.id.person_age);
}
}
}
Then in your Activity:
...
RecyclerView rv = (RecyclerView)findViewById(R.id.rv);
rv.setHasFixedSize(true);
LinearLayoutManager llm = new LinearLayoutManager(mContext);
rv.setLayoutManager(llm);
final RVAdapter rvAdapter = new RVAdapter(personList);
rv.setAdapter(rvAdapter);
RequestQueue requestQueue = Volley.newRequestQueue(mContext);
String url = "http://192.16.1.100/api/persons";
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
if (response.length() > 0) {
personList.clear();
for (int i = 0; i < response.length(); i++) {
JSONObject jsonObject = response.getJSONObject(i);
Person person = new Person();
if (!jsonObject.isNull("name")) {
person.name = jsonObject.getString("name");
}
if (!jsonObject.isNull("age")) {
person.age = jsonObject.getInt("age");
}
personList.add(i, person);
}
rvAdapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// do something
}
});
requestQueue.add(jsonArrayRequest);
...
Here is the result
Hope this helps!
I have an Action class with 4 action methods.
All four action action methods use a json result.
Via logging statements and debugging, I have verified that if I call action method 1, action method 2 and 3 are also called. But not 4. Finally, action method 1 is called again and the json result is generated
If I change the result type of Action method 1 to the default dispatcher with a jsp location, only action method 1 is called. (this is the behavior I want with the json result)
Hope that makes sense.
Anyone have any ideas?
This question was asked here https://stackoverflow.com/questions/3767698/struts2-if-result-type-json-and-method-defined-then-all-methods-get-invoked
But there was no answer.
Please let me know if you need more information.
#ResultPath("/WEB-INF/jsp/dta/")
public class GroupEntityAction extends BaseAction {
/**
*
*/
private static final long serialVersionUID = 6750675222824235086L;
private static Logger log = Logger.getLogger(GroupEntityAction.class);
private List<EntityBusiness> theUnusedEntityBusinessList;
private String assignedEntities[];
private long groupId;
private long businessId;
private String parentMe;
private long rptYear;
private String ssoId;
private String isSubmitted;
private String delimGoLiveEmails;
private List<String> theEmailList;
#Action(value = "ajaxGetAvailableEntityList",
results = { #Result(name = "success", type = "json") }
,
interceptorRefs = { #InterceptorRef("dtaStack"),
#InterceptorRef(value = "dtaStack", params = { "appInterceptor.allowedRoles", "ADMIN" }) }
)
public String getEntityListsByBusiness() throws Exception {
if (rptYear == 0) {
return SUCCESS;
}
LookupService theSvc = new LookupService();
if (businessId != 0) {
setTheUnusedEntityBusinessList(theSvc.getAvailableEntityListBizExceptIds(rptYear, businessId, ssoId, assignedEntities));
} else {
setTheUnusedEntityBusinessList(theSvc.getAvailableEntityListParentMeExceptIds(rptYear, parentMe, ssoId, assignedEntities));
}
log.debug(theUnusedEntityBusinessList.size());
return SUCCESS;
}
#Action(value = "ajaxToggleGroupBusinessSubmitted",
results = { #Result(name = "success", type = "json") }
,
interceptorRefs = { #InterceptorRef("dtaStack") }
)
public String toggleGroupBusinessReview() {
try {
new ProformaService().toggleIsSubmitted(getCurrentUser().getSsoId(), groupId, rptYear, businessId);
} catch (SQLException e) {
log.error(e.getMessage());
return ERROR;
}
return SUCCESS;
}
#Action(value = "ajaxGetGoLiveEmailList",
results = { #Result(type = "json") }
,
interceptorRefs = { #InterceptorRef("dtaStack"),
#InterceptorRef(value = "dtaStack", params = { "appInterceptor.allowedRoles", "ADMIN" }) }
)
public String getGoLiveEmailList() {
try {
List<TaxUser> theUserList = new SecurityService().getAll();
List<String> theEmailList = new ArrayList<String>();
for (TaxUser theUser : theUserList) {
if ((!theUser.getRoles().contains("ADMIN")) && (theUser.getIsActive().equalsIgnoreCase("Y"))) {
if (!theEmailList.contains(theUser.getEmail())) {
theEmailList.add(theUser.getEmail());
}
}
}
setDelimGoLiveEmails(StringUtils.join(theEmailList.toArray(), "|"));
setTheEmailList(theEmailList);
} catch (SQLException e) {
log.error(e.getMessage());
return ERROR;
}
return SUCCESS;
}
#Action(value = "ajaxGetChaserEmailList",
results = { #Result(name = "success", type = "json") }
,
interceptorRefs = { #InterceptorRef("dtaStack"),
#InterceptorRef(value = "dtaStack", params = { "appInterceptor.allowedRoles", "ADMIN" }) }
)
public String getChaserEmailList() {
try {
List<String> theEmailList = new LookupService().getChaserEmailList();
setDelimGoLiveEmails(StringUtils.join(theEmailList.toArray(), "|"));
setTheEmailList(theEmailList);
} catch (SQLException e) {
log.error(e.getMessage());
return ERROR;
}
return SUCCESS;
}
public void setTheUnusedEntityBusinessList(
List<EntityBusiness> theUnusedEntityBusinessList) {
this.theUnusedEntityBusinessList = theUnusedEntityBusinessList;
}
public List<EntityBusiness> getTheUnusedEntityBusinessList() {
return theUnusedEntityBusinessList;
}
public void setAssignedEntities(String assignedEntities[]) {
this.assignedEntities = assignedEntities;
}
public String[] getAssignedEntities() {
return assignedEntities;
}
public void setGroupId(long groupId) {
this.groupId = groupId;
}
public long getGroupId() {
return groupId;
}
public void setBusinessId(long businessId) {
this.businessId = businessId;
}
public long getBusinessId() {
return businessId;
}
public void setParentMe(String parentMe) {
this.parentMe = parentMe;
}
public String getParentMe() {
return parentMe;
}
public void setRptYear(long rptYear) {
this.rptYear = rptYear;
}
public long getRptYear() {
return rptYear;
}
public void setSsoId(String ssoId) {
this.ssoId = ssoId;
}
public String getSsoId() {
return ssoId;
}
public void setIsSubmitted(String isSubmitted) {
this.isSubmitted = isSubmitted;
}
public String getIsSubmitted() {
return isSubmitted;
}
public void setDelimGoLiveEmails(String delimGoLiveEmails) {
this.delimGoLiveEmails = delimGoLiveEmails;
}
public String getDelimGoLiveEmails() {
return delimGoLiveEmails;
}
public void setTheEmailList(List<String> theEmailList) {
this.theEmailList = theEmailList;
}
public List<String> getTheEmailList() {
return theEmailList;
}
}
In this action class, I attempting to call ajaxGetGoLiveEmailList, and what I get is ajaxGetGoLiveEmailList called first, and then ajaxGetChaserEmailList, and then ajaxGetAvailableEntityList, and then ajaxGetGoLiveEmailList gets called again. ajaxToggleGroupBusinessSubmitted is skipped.
If I change the result annotation of ajaxGetGoLiveEmailList to
results={#Result(location="something.jsp")
, only ajaxGetGoLiveEmailList get called.
When I look at the config browser, all the action mapping are configured correctly, pointing to the correct method calls.
JSON plugin may be calling all your methods that start with "get" in an attempt to serialize them for output. Try renaming your methods to something else.