How to get Intent first and then only create a fragment? - android-fragments

In one of my activities onCreate method I'm passing in an ArrayList from an intent into the fragment to create the fragment. However, I realised it would throw null pointer exception as the fragment might be created before receiving the intent?How should I fix this?In my onCreate method.
monitor_list= this.getIntent().getParcelableArrayListExtra("monitorList");
cholesterol_monitor = (ArrayList<CholesterolMonitor>) monitor_list;
monitorListFragment = MonitorListFragment.newInstance(cholesterol_monitor);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_monitor_layout, monitorListFragment)
.commit();

check first if the monitor_list is not null then if it's not replace the fragment
ArrayList<CholesterolMonitor> monitor_list= this.getIntent().getParcelableArrayListExtra("monitorList");
if (monitor_list.size()>0){
cholesterol_monitor = (ArrayList<CholesterolMonitor>) monitor_list;
monitorListFragment = MonitorListFragment.newInstance(cholesterol_monitor);
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.fragment_monitor_layout, monitorListFragment)
.commit();
}else // list is null

Related

BindingResult.getFieldValue() returning null in test context for a formatted value

In a spring mvc app, I submit id's and use a formatter to convert that id to an object. It works well in the container.
But in the unit test environment, I'm seeing a problem.
I mock the formatter to always return my test value, this is fine it gets injected into the ModelAttribute. But in the BindingResult, a call to result.getFieldValue("location") for example is returning null, but only in the MockMvc context.
This is the test case:
/**
* Tests the inventory update for existing inventory records.
* #throws Exception
*/
#Test
public void testUpdateExistingProductInventory() throws Exception{
logger.entry();
VariantInventory oldInventory = new VariantInventory();
oldInventory.setId(20l);
Product product = ProductBuilder.buildBasicExisting();
Location location = new Location();
location.setId(3l);
ProductVariant variant = new ProductVariant();
variant.setId(2l);
// check the formatter is working
Mockito.when(mockProductFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(product);
Product p = mockProductFormatter.parse("1", null);
Assert.assertEquals(p, product);
// check the formatter is working
Mockito.when(mockLocationFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(location);
Location l = mockLocationFormatter.parse("3", null);
Assert.assertEquals(l, location);
// check the formatter is working
Mockito.when(mockVariantFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(variant);
ProductVariant pv = mockVariantFormatter.parse("2", null);
Assert.assertEquals(pv, variant);
// check the formatter is working
Mockito.when(mockInventoryFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(oldInventory);
VariantInventory v = mockInventoryFormatter.parse("20", null);
Assert.assertEquals(v, oldInventory);
this.mockMvc.perform(MockMvcRequestBuilders.post("/ajax/products/update/inventory")
.param("product", "1")
.param("variant", "2")
.param("location", "3")
.param("status", "ACTIVE")
.param("quantityOnHand", "30.5")
.param("lowStockQuantity", "10")
.param("inventory", "20")
)
.andExpect(status().isOk());
Mockito.verify(mockInventoryService, Mockito.times(1)).updateExisting(Mockito.eq(oldInventory), Mockito.any(VariantInventory.class));
logger.exit();
}
This is the relative part of the controller:
#RequestMapping(value = "/ajax/products/update/inventory", method= RequestMethod.POST)
public #ResponseBody
AJAXResponse updateProductInventory(#ModelAttribute ProductInventoryFormWrapper formWrapper, BindingResult result,
ModelMap map) {
logger.entry();
logger.debug("Getting product data");
if (!result.hasErrors()) {
inventoryValidator.validate(formWrapper, result);
}
}
Then skipping a few items, this is the relevant validation that fails, where I am passing location as the field.
ValidationUtils.rejectIfEmptyOrWhitespace(errors, field, "required.field", new String[]{label});
The object fails to validate because of what must be a bug.
What I observe if I debug the controller is:
The object is in the FormWrapper, and the properties are there.
But in the BindingResult object, if I call 'getFieldValue('location')` which is what's being called in the spring validation code, it's returning null, and therefore the validator rejects the value.
So for some reason the binding result hasn't registered the formatted fields or something. Note that this only happens in the Unit Test, not in the container.
Does anyone know how to fix?
Quick Edit:
I've done some more debugging, and it's failing in this block of code from AbstractPropertyBindingResult. The value is okay right up until the conversionService is called to convert it. I haven't downloaded the source beyond that method, so I can't see exactly why it's failing, but somewhere in the convert method it's being turned from the proper value, to null. I presume because I'm using MockObjects, and maybe it's calling something that I haven't anticipated to return the value.
#Override
protected Object formatFieldValue(String field, Object value) {
String fixedField = fixedField(field);
// Try custom editor...
PropertyEditor customEditor = getCustomEditor(fixedField);
if (customEditor != null) {
customEditor.setValue(value);
String textValue = customEditor.getAsText();
// If the PropertyEditor returned null, there is no appropriate
// text representation for this value: only use it if non-null.
if (textValue != null) {
return textValue;
}
}
if (this.conversionService != null) {
// Try custom converter...
TypeDescriptor fieldDesc = getPropertyAccessor().getPropertyTypeDescriptor(fixedField);
TypeDescriptor strDesc = TypeDescriptor.valueOf(String.class);
if (fieldDesc != null && this.conversionService.canConvert(fieldDesc, strDesc)) {
return this.conversionService.convert(value, fieldDesc, strDesc);
}
}
return value;
}
Ok that was a tough one, so I didn't really expect anyone to answer. But here's the answer. I was right, the Mock was being called in the validation. So I had to add an additional mock method to the formatters (print):
// check the formatter is working
Mockito.when(mockInventoryFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(oldInventory);
// this was added
Mockito.when(mockInventoryFormatter.print(Mockito.any(VariantInventory.class), Mockito.any(Locale.class))).thenReturn("20");

Passing Object to Fragment

I am trying to pass an ArrayList to a fragment as arguments but the argument seems to be empty.
This is my code of the mainActivity where I create and launch the fragment, which btw works.
ArrayList<HashMap<String, String>> myeventListRefImages; //has data
imageFragment = new ImageMyEventRefFragment();
fragmentManager.findFragmentById(fragmentId);
if (findViewById(R.id.fragment_image) != null) {
if (savedInstanceState != null) {
return;
}
getIntent().putExtra("mERImageList", myeventListRefImages); //working
Bundle bundle = new Bundle(); //doesn’t work
bundle.putSerializable("mERImageList", myeventListRefImages);//doesn’t work
imageFragment.setArguments(bundle);
[…]
}
So far, I only get to manage it with putExtra but in that case, the extra never seems to be empty later on which is kind annoying in case I want to skip the if argument :(
That’s the code of my fragment:
public void onStart() {
super.onStart();
Bundle args = getArguments();//doesn’t work //empty at all
Bundle extras = getActivity().getIntent().getExtras();//works
if (args != null) {
System.out.println("Args!");
}
}
Any idea? I event cant debug the fragment to check the value of the getArugments comment there the app just crashes, but when I run it normally I can use System out commands.

Transaction never finished Neo4j

I have a method which should create a sub-graph defined this way:
#Transactional
public Post createAndLink(Appuser appuser, Post post, String linkTo) {
Post savedPost = null;
if(post != null && appuser != null){
post.setCreatedBy(appuser);
if(post.getId() == null && post.getId() == ""){
post.setId("IND"+GenerateUUID.getUUID());
}
System.out.println(">>> Id created : "+post.getId());
//Date check
String d = post.getDate();
if(d != null && d.length() == 11 && ConversionUtils.isNumeric(d.substring(0, 4))
&& ConversionUtils.isNumeric(d.substring(5, 7)) && ConversionUtils.isNumeric(d.substring(8, 10))){
if(!ConversionUtils.isPastDate(d)){
System.out.println("Cannot save post with date after today");
return null;
}
}
System.out.println(">>> Date created : "+post.getDate());
//People check
Set<People> people = new HashSet<People>();
if(post.getPeople() != null){
for(People p : post.getPeople()){
People pFromDb = peopleService.findById(p.getId());
people.add(pFromDb != null ? pFromDb : new People("PPL"+GenerateUUID.getUUID(), p.getName()));
}
post.setPeople(people);
}
System.out.println(">>> People created : "+post.getPeople());
//Place check
if(post.getPlace() != null){
Place pFromDb = placeService.findById(post.getPlace().getId());
post.setPlace(pFromDb != null ? pFromDb : new Place(post.getPlace().getId()));
}
System.out.println(">>> Place created : "+post.getPlace());
System.out.println("Post checking OK.");
savedPost = repository.findById(linkTo);
if(savedPost != null){
Set<Post> linked = new HashSet<Post>();
linked.add(savedPost);
post.setLinkedPosts(linked);
}
template.save(post);
System.out.println("=====> [saveWithUser]: Saved OK!");
}
return savedPost;
}
When I call this method within a loop, sometimes it gets stuck (in one of the iterations) in the execution of template.save(post).
The same behaviour is observed when I call this method unitarily from a GUI.
PS: The findBy methods are not transactional.
I'm stuck on it since 2 weeks and I can't find a way to solve it :/
Thanks for any feedback.
Edit 1:
Logs produced by the method:
>>> Id created : IND6f770750-7834-40ae-a07e-fc81bbb3c657
>>> Date created : 2009Y09M20D
>>> People created : [People [id=PPLaf830449-b15c-4c71-b706-abd11492b825, name=Mary], People [id=PPLdf53d2c7-06b1-49c8-9b69-3b765d9b2ee6, name=Laptop]]
>>> Place created : Place [id=2918548, name=null]
Post checking OK.
PS: The iteration before the blocked one, it shows a normal log execution but nothing created in the DB
Edit 2:
And sometimes I get this error (always during the 2nd iteration while 1st shows normal logs but writes nothing on DB):
javax.transaction.RollbackException: Tx status is: STATUS_MARKED_ROLLBACK
I think I found the problem (but not yet the solution)
I removed all #Transactional annotations from my service methods (controllers and repositories are not marked as Transactional).
In the method createAndLink described in the main post I added transaction this way :
if(post != null && appuser != null){
Transaction tx = template.getGraphDatabaseService().beginTx();
//I kept the same code...
//...
tx.success();
tx.close();
}
Now, when I call this method from a controller A, the tx is of type Placebo. When I call it from a controller B, the tx type is a TopLevel.
I even made a test with calling the controller A method from the controller B (like in the example below) and it worked perfectly (with a TopLevel Tx). When I do the opposite way, the Tx is Placebo.
Controller A:
#RequestMapping(value="/newandlinksimilar/{linkedTo}", method=RequestMethod.POST)
public #ResponseBody boolean createAndLinkNewSimilar(#RequestBody Post post, #PathVariable String linkedTo){
Post created = null;
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (post!= null && !(auth instanceof AnonymousAuthenticationToken)) {
AppuserDetails userDetails = (AppuserDetails)auth.getPrincipal();
Appuser currentUser = appuserService.findByLogin(userDetails.getUsername());
created = postService.createAndLinkSimilar(currentUser, post, linkedTo);
}
return created;
}
Controller B:
#autowired
private ControllerA controllerA;
#RequestMapping("/init")
public ModelAndView init(){
//I create a new Post object "post" with dummy data
controllerA.createAndLinkSimilar(post,"XXXXXX");
//Or postService.createAndLinkSimilar(appuser,post,"XXXXXX");
return new ModelAndView("home");
}
Both tests are made from a GUI ajax call to the controller method.
I can't understand when and how Spring choose the type of the transaction?!

How to pass data from main activity to fragment

i am a newbie in android development. I am now seeking a solution on how i can pass a value from main activity to different fragments. My apps have a main activity and 5 fragments. I would like to do xml parsing in my main and then pass processed data to different fragments so that i can draw different pages at the same time. My main has set a new fragment adapter
mAdapter = new FragmentAdapter(getSupportFragmentManager());
And then in my FragmentAdapter (which extend FragmentPagerAdapter and implements IconPagerAdapter), i have overwrite the getItem method so that i can create 5 fragment to handle 5 different pages.
#Override
public Fragment getItem(int position) {
Fragment fragment = new Fragment1();
switch(position){
case 0:
fragment = new Fragment1();
break;
case 1:
fragment = new Fragment2();
break;
case 2:
fragment = new Fragment3();
break;
case 3:
fragment = new Fragment4();
break;
case 4:
fragment = new Fragment5();
break;
}
return fragment;
}
My question is how i can pass some value from my main to the newly generated fragments.For e.g i would like to pass a value "A" from my main to fragment 1. How can i do this task? Tks in advance for your help!~
You can have a look at this article: http://developer.android.com/training/basics/fragments/communicating.html
Tony, in the link http://developer.android.com/training/basics/fragments/communicating.html
ArticleFragment newFragment = new ArticleFragment();
Bundle args = new Bundle();
args.putInt(ArticleFragment.ARG_POSITION, position);
newFragment.setArguments(args);
The above code snippet allows the MainActivity to pass an int data to the ArticleFragment class.
ArticleFragment class then can use code snippet below to read the int data in say its onCreate method.
int position = getArguments().getInt(ARG_POSITION);

Populate ListView with data from SQLite database

I've been beating my head around trying to populate a ListView with data from an SQLite database and can't seem to figure it out. I've read countless tutorials and equally countless posts here, but I'm obviously not getting something critical. Was hoping someone could give me a hint as to why the following two pieces of code aren't working together, or if I should be looking at something else entirely. Any help would be appreciated. The result I'm getting is a force close.
Method that initiates populating ListView object
public void displayNurseRoster(){
listView = (ListView) findViewById(R.id.list);
// create instance of DbCommunicator
DbCommunicator rosterView = new DbCommunicator(this);
// open instance
rosterView.open();
// instantiate SimpleCursorAdapter instance and set value
SimpleCursorAdapter cursorAdapter;
cursorAdapter = rosterView.getRosterListViewAdapter(this);
// close database instance
rosterView.close();
// set adapter to listView
listView.setAdapter(cursorAdapter);
}
Method that returns SimpleCursorAdapter:
public SimpleCursorAdapter getRosterListViewAdapter (Context context) {
// method variables
int[] to = new int[] {R.id.rosterListLname};
// used ArrayList because of unpredictability of array length
List<String> dataArray = new ArrayList<String>();
String[] columns = new String[] {KEY_NURSE_ROWID, KEY_LNAME};
// create cursor
Cursor cursor = sqldb.query(NURSE_TABLE, columns, null, null, null,
null, KEY_LNAME);
int iLname = cursor.getColumnIndex(KEY_LNAME);
cursor.moveToFirst();
String result = "";
while(!cursor.isAfterLast()){
result = result
+ cursor.getString(iLname) + "\n";
dataArray.add(result);
}
// convert ArrayList to String array for use with SimpleCursorAdapter
String [] from = (String[]) dataArray.toArray();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(context,
R.layout.edit_roster, cursor, from, to);
return adapter;
}
Okay, I got it to work and wanted to share to help out anyone else struggling with this and 2) to get feedback on my fix in case anyone with more experience has a better suggestion.
I actually wanted to show three items in the list view, so here's the code that worked. One of the problems I was having was that I was extending ListActivity, but found in another StackOverflow post that that is not a good idea when there is only one list view to worry about.
package com.deadEddie.staffingmanagement;
import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
public class EditRoster extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_roster);
displayNurseRoster();
}
public void displayNurseRoster(){
ListView listView = (ListView) findViewById(R.id.list);
int[] to = new int[] {
R.id.rosterListLname,
R.id.rosterListFname,
R.id.rosterListMI };
String[] from = new String [] {
DbCommunicator.KEY_LNAME,
DbCommunicator.KEY_FNAME,
DbCommunicator.KEY_MI};
// create instance of DbCommunicator
DbCommunicator rosterView = new DbCommunicator(this);
// open instance
rosterView.open();
// get & manage cursor
Cursor cursor = rosterView.getRosterCursor(this);
startManagingCursor(cursor);
// instantiate cursor adaptor
ListAdapter adapter = new SimpleCursorAdapter(this,
R.layout.nurse_list, cursor, from, to);
cursor.moveToNext();
// set adapter to listView
listView.setAdapter(adapter);
}// displayNurseRoster()
}
Here's the method in my DbCommunicator class. What finally made the difference was that I was not creating an instance of SQLiteQueryBuilder and using that, but instead I was using sqldb.query(...), as shown above. I'm not sure what the difference is, but it finally did the trick. If anyone would like to share, please do.
public Cursor getRosterCursor (Context context) {
SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(NURSE_TABLE);
Cursor cursor = queryBuilder.query(sqldb, new String[] {
KEY_NURSE_ROWID,
KEY_LNAME,
KEY_FNAME,
KEY_MI},
null, null, null, null, null);
return cursor;
}
A couple other newbie lessons for anyone else out there:
1. Always use the "_id" field in the cursor. The cursor cannot function without that.
2. The while or for loop is not necessary for a simple list view. The cursor adapter handles that.
3. There is no need to call the moveToFirst() method on the cursor.
Hope that's helpful to someone.

Resources