I have a general question for Android "best practices".
Let's take a fragment for example, where i need to have access to the activity multiple times.
I can do the following:
1- Keep calling getActivity()
2- Override the onAttach() method of the fragment, save the Acitivty as a variable once and keep using it throughout the fragment, like so:
private Activity activity;
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.activity = (Activity) context;
}
Is there any difference between both methods? which is considered better for performance/memory/etc.?
While watching a random Android talk i got an amazing answer to my questions by Jake Wharton.
The answer is NOT to call getActivity() multiple times. Just save the activity as a field for reuse.
Link for the talk: https://www.youtube.com/watch?v=b6zKBZcg5fk
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I am developing a new WebApi using .NetCore2.2, Autofac4, Dapper. There are few very basic questions because this is my first WebApi project. As part of this project I have to write both unit-test and integration-test.
My questions are as follows (Sample Code is give below):
What is recommended return type between "Task< IActionResult >" and "Task< IEnumerable >"?
Recommended object Scope of the dependencies in startup class for my project?
Do I really need UnitOfWork for this given project structure?
What are the flaws if I follow this design?
Is there any better way to design this API?
As TDD do I need write test cases for API layer(Controller) and Infrastructure layer only or Doman Layer (it doesn't have any logic) as well?
What are the scenario I must include in my controller unit test?
Domain Layer:
[Table("Movie")]
public class Movie
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID {get;set;}
public string Title {get;set;}
}
public interface ICommandRepository<T> where T : class
{
Task CreateAsync(T entity);
Task UpdateAsync(T entity);
Task DeleteAsync(T entity);
}
public interface IQueryRepository<T> where T : class
{
Task<IEnumerable<T>> GetAllMoviesAsync();
Task<IEnumerable<T>> GetMoviesByTitleAsync(string title);
Task<T> GetMovieByIDAsync(int id);
}
Infrastructure Layer:
public class MovieCommandContext : DbContext
{
public MovieCommandContext(DbContextOptions<MovieCommandContext> options)
: base(options)
{}
public DbSet<Movie> Movies { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
public class MovieQueryContext : IDisposable
{
private readonly IDbConnection connection;
public MovieQueryContext(string connectionString)
{
connection = new SqlConnection(connectionString);
}
public async Task<IEnumerable<Movie>> GetAllMovies()
{
// Use Dapper->QueryAsync
throw new NotImplementedException();
}
...
public void Dispose()
{
if (connection?.State == ConnectionState.Open)
connection.Close();
}
}
public class MovieCommandRepository : ICommandRepository<Movie>
{
private readonly MovieCommandContext context;
public MovieCommandRepository(MovieCommandContext dbContext)
{
context = dbContext;
}
public async Task CreateAsync(Movie movie)
{
await context.AddAsync<Movie>(movie);
await context.SaveChangesAsync();
}
public async Task UpdateAsync(Movie movie)
{
var entity = context.Attach<Movie>(movie);
context.Entry<Movie>(movie).State = EntityState.Modified;
await context.SaveChangesAsync();
}
public async Task DeleteAsync(Movie movie)
{
context.Remove<Movie>(movie);
await context.SaveChangesAsync();
}
}
public class MovieQueryRepository : IQueryRepository<Movie>
{
private readonly MovieQueryContext context;
public MovieQueryRepository(MovieQueryContext dbContext)
{
context = dbContext;
}
public async Task<IEnumerable<Movie>> GetAllMoviesAsync()
{
return await context.GetAllMovies();
}
public async Task<IEnumerable<Movie>> GetMoviesByTitleAsync(string title)
{
return await context.GetMovieByName(title);
}
public async Task<Movie> GetMovieByIDAsync(int id)
{
return await context.GetMovieByID(id);
}
}
API Layer:
[Route("api/sample")]
[ApiController]
public class SampleController : ControllerBase
{
private readonly ICommandRepository<Movie> movieCommand;
private readonly IQueryRepository<Movie> movieQuery;
public SampleController(ICommandRepository<Movie> command, IQueryRepository<Movie> query)
{
movieCommand = command;
movieQuery = query;
}
[HttpGet]
public async Task<IActionResult> GetMoviesAsync()
{
try
{
var movies = await movieQuery.GetAllMoviesAsync();
return Ok(movies);
}
catch
{
// TODO: Logging
return BadRequest();
}
}
[Route("{name:alpha}")]
[HttpGet]
public async Task<IActionResult> GetMoviesByTitle(string movieTitle)
{
try
{
var movies = await movieQuery.GetMoviesByTitleAsync(movieTitle);
return Ok(movies);
}
catch
{
// TODO: Logging
return BadRequest();
}
}
[Route("{movieID:int:min(1)}")]
[HttpGet]
public async Task<IActionResult> GetMovieByID(int movieID)
{
try
{
var movie = await movieQuery.GetMovieByIDAsync(movieID);
return Ok(movie);
}
catch
{
// TODO: Logging
return BadRequest();
}
}
[Route("")]
[HttpDelete("{id:int:min(1)}")]
public async Task<IActionResult> Delete(int id)
{
try
{
var movie = await movieQuery.GetMovieByIDAsync(id);
if (movie == null)
return BadRequest();
await movieCommand.DeleteAsync(movie);
return Ok();
}
catch
{
// TODO: Logging
return BadRequest();
}
}
}
Startup.cs:
private void ConfigureContainer(ContainerBuilder builder)
{
var contextOptions = new DbContextOptionsBuilder<MovieCommandContext>()
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
.Options;
builder.RegisterType<MovieCommandContext>()
.WithParameter("options", contextOptions);
builder.RegisterType<MovieQueryContext>()
.AsSelf()
.WithParameter("connectionString",Configuration.GetConnectionString("DefaultConnection"));
builder.RegisterType<MovieCommandRepository>().As<ICommandRepository<Movie>>();
builder.RegisterType<MovieQueryRepository>().As<IQueryRepository<Movie>>();
}
Point 1:
You should return an IActionResult to return a propper Http response, instead of returning the Task<IEnumerable<Movie>>. That way you guarantee the S and the I of SOLID principles
Point 2 & 3:
see here: Entity Framework Core service default lifetime
Point 4:
IQueryRepository as some bad methods names. The names are tight coupled with domain concepts and they should not.
You are failing the Separation of concerns ( the S of SOLID).
ICommandRepository as an Add method that is being expose to some controller and not being used ( same as Update) here you are failing on the Interface segregation.
MovieQueryContext does not implement IDisposable pattern correctly please see here!
MovieQueryContext is different from MovieCommandContext on the way it initializes. Why? You should try to be coherent the way you design you types because it will give you reusability and apply the DRY principle.
Consider the effort you will need to to if the access to the database change to mongodb. Or if the access to the database changes to a remote service How many changes, and where do you do does changes to support that?
If Movie is a Domain Type it should not have attributes to any specific database access. keep it POCO as possible.
Point 5:
To design your API consider this post. The way you inject your dependencies should consider the lifetime of those objects. Keep in mind that in aspnet.core ApiControllers lifetime is per request. The way you manage your resources to access database should take that into consideration.
If you are considering CQRS, the controllers should be diferent. Keeping in mind the Separation of concerns regarding those responsabilities. One controller would have the responsability to expose some query API, and the other to process commands. There are good frameworks to support CQRS see this scott hanselman post.
Constraints exists on Route attribute not on Verbs.
Logging and Exception handling should be done on an ActionAttribute or on some Especific Middleware, because they are considered to be cross cutting concerns.
Delete Action does not comply to the Http protocol. please consider http rfc:
GetMoviesByTitle Action does not have the name parameter.
Point 6:
Unit tests should test business logic, mocking all the external dependencies with values relevant to the test in place. TDD methodology considers 3 main steps ( here for more details):
the first step consists on implementing the unit tests so it fails
Iterate on implementation of the method being test until it passes with success
Improve the implementation of the method being test
If you want to test your ApiController as being used with all the middleware integrated you need to have that environment put in place without using an actual server that open ports. To do that please consider the usage of TestServer ( see here and here )
1. What is recommended return type between "Task< IActionResult >" and "Task< IEnumerable < Movie > >"?
Even though the API allows you yo use the interface IActionResult, I wouldn't use it at all. Why? Semantics, the only way to know what the true return is, is to see the implementation. It's clearer if the returns is Task< IEnumerable< Movie>>.
If you need to throw a BadRequest or other http code, use the asp.net pipeline to handle this for you. See Notes below.
When using whatever tool to generate some sort of documentation of this API it won't help hiding the real result.
2. object Scope of the dependencies in startup class for my project?
Avoid sharing state between calls, to avoid future issues with synchronization just stick to scope dependencies per request. This may be a performance issue if you have a lot of requests, you can always change this later on. If it's an issue at all.
3. I really need UnitOfWork for this given project structure?
4. What are the flaws if I follow this design?
5. Is there any better way to design this API?
In hope of answering the above 3 questions. The problem I see is extending the functionality around Movie model. e.g. add a fourth action on ICommandRepository.
It seams it will grow vertically. It will only be a problem if multiple classes implement this interface, because they will all need to change. (Interface Segregation Principle)
A way to solve this is to use the Mediator pattern. Your controller will receive the mediator and the mediator will deliver the message to whoever handles it. With this type of solution you could have a class per operation and therefore your system can grow horizontally as new classes are added to the system. (Open Close Principle)
In time, you'll see that a lot of functionality can be reused and adding features is just a matter of configuration.
6. As TDD do I need write test cases for API layer(Controller) and Infrastructure layer only or Domain Layer (it doesn't have any logic) as well?
The idea of Testing in general is to test behavior, when TDDing that should be your mindset. In my experience I found that testing the whole behavior is better than multiple parts of the same behavior.
In this case, the API Layer is part of the infrastructure as is the persistence layer. They should have their own tests, the business rules (Application layer) should have their own tests. The application layer is what you want to last forever. The Api will change as technologies appear (windows forms, web forms, web apis, etc.) Regarding databases as well, you don't know if you want to stick with EF forever.
If the domain layer doesn't provide any behavior then there is nothing to test.
7. What are the scenario I must include in my controller unit test?
I would test using asp.net TestHost:
https://learn.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-2.2
Test the if routing is correct, test failing scenarios and successful scenarios.
Some notes:
An exception in the Controller does not mean a BadRequest.
Logging is a cross cutting concern, don't just do it everywhere.
Either use the asp.net pipeline or just move this concern to
application layer.
It appears that MovieQueryRepository does nothing, so you don't need it.
This is just some remarks about your questions, there is much more to it. Just remember to keep things simple and organized.
Hope it helped, let me know!
is it possible to create custom effects for JavaFX, based on a Pixle Shader? I found this article but what is Decora? I cannot find anything about it.
THX
Currently no - in the abstract base class Effect.java, there are abstract package-private methods like, copy(), sync(), update() etc.
The Decora project is discussed here: http://labonnesoupe.org/static/code/ . I asked about opening JSL, to make some kind of public API in the developer OpenJFX thread perhaps 6 months ago, and was told, "no, there are no plans to open this api to the public".
As you may be aware, OpenJFX are considering new committers, which works, I believe on the premise that you sign an Oracle contributor agreement, and are voted in by lazy consensus. Perhaps this will shunt this much needed area into life.
In my own 2D game, I use Guassian Blurs, and Blooms, to highlight spell strikes, and I believe Decora was used in developing these Effects. However, they are pitifully slow. Taking my FPS from around 250 down to around 30 on a 10 series NVidia card. I would love to see improvements here.
I emailed Chris Campbell (author of Labonnesoupe) asking about his work on JavaFX shaders, but he emailed me back to say it was over 8 years ago, and he's not up on the latest. A search of web reveals that all reference to Decora is now ancient.
Theoretically it is possible to create you custom effect in JavaFx however using way u probably won't like. Abstract class javafx.scene.effect.Effect has internal methods inside, that is right. But based on the fact that internal means "package private" we can do the following. In your project create a new package called "javafx.scene.effect" the same as Effect class is in, and inside this newly created package just create your custom effect class that extends javafx.scene.effect.Effect and that's it you have your custom JavaFx effect.
Custom Effect class example:
package javafx.scene.effect;
import com.sun.javafx.geom.BaseBounds;
import com.sun.javafx.geom.Rectangle;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.javafx.scene.BoundsAccessor;
import com.sun.scenario.effect.FilterContext;
import com.sun.scenario.effect.ImageData;
import javafx.scene.Node;
public class MyEffect extends javafx.scene.effect.Effect
{
public MyEffect()
{
}
#Override
com.sun.scenario.effect.Effect impl_createImpl()
{
return new com.sun.scenario.effect.Effect()
{
#Override
public boolean reducesOpaquePixels()
{
// TODO Auto-generated method stub
return false;
}
#Override
public BaseBounds getBounds(BaseTransform transform, com.sun.scenario.effect.Effect defaultInput)
{
// TODO Auto-generated method stub
return null;
}
#Override
public AccelType getAccelType(FilterContext fctx)
{
// TODO Auto-generated method stub
return null;
}
#Override
public ImageData filter(FilterContext fctx, BaseTransform transform, Rectangle outputClip, Object renderHelper, com.sun.scenario.effect.Effect defaultInput)
{
// TODO Auto-generated method stub
return null;
}
};
}
#Override
void impl_update()
{
// TODO Auto-generated method stub
}
#Override
public BaseBounds impl_getBounds(BaseBounds bounds, BaseTransform tx, Node node, BoundsAccessor boundsAccessor)
{
// TODO Auto-generated method stub
return null;
}
#Override
boolean impl_checkChainContains(javafx.scene.effect.Effect e)
{
// TODO Auto-generated method stub
return false;
}
#Override
public javafx.scene.effect.Effect impl_copy()
{
// TODO Auto-generated method stub
return null;
}
}
However I have literally no idea what those inhered methods in from javafx.scene.effect.Effect supposed to do so you need to figure it out :)
Also, keep in mind that internal/private things are private for some reason (even though I also do not see that reason in this case)!
Aditional: What I currently know is that JavaFx Effects are only some sort of "masks" or "providers" for Effects from `com.sun.scenario.effect` and there are many com.sun.scenario.effect children classes that have no direct JavaFx version/implementation so you should be theoretically able to add these ones into JavaFx by your self using my solution! But again there is a question if this is a good idea because I think `com.sun.scenario.effect` is something that regular JavaFx programer supposed to not even know about. But I will let you to decide!
Use libgdx. Its free and Works on Web HTML 5 webgl ,ios,android,all desktop and with full shader support
I got some operations in my Controller class which could take some time. So I want to show a loading dialog while this operation is running.
I tried this:
Platform.runLater(new Runnable() {
#Override
public void run() {
loadingDialog.show();
}
});
Boolean opSuccess = myService.operate();
Platform.runLater(new Runnable() {
#Override
public void run() {
loadingDialog.hide();
}
});
if (opSuccess) {
// continue
}
Now, the Problem is, the loadingDialog is never show. The UI only blocks for some time and than continues on "//continue".
So it seems, the runLater call is blocked by the blocking operation (operate)?
I also tried CoundDownLatch, to wait for loadingDialog.show() to complete, before running myService.operate(). But the latch.await() method never completes.
So my question is, how my I show the loadingDialog until myService.operate() finished and returned true or false? Do I have to put the operate() call into another thread and run it async or is there an easier way?
Thanks for help.
Are you sure your entire code does not run in the JavaFX Thread?
Methods of your controller class usually do and I assume it due to your description.
However, better use the Task class. Here you'll find a tutorial and a short snippet for your application:
// here runs the JavaFX thread
// Boolean as generic parameter since you want to return it
Task<Boolean> task = new Task<Boolean>() {
#Override public Boolean call() {
// do your operation in here
return myService.operate();
}
};
task.setOnRunning((e) -> loadingDialog.show());
task.setOnSucceeded((e) -> {
loadingDialog.hide();
Boolean returnValue = task.get();
// process return value again in JavaFX thread
});
task.setOnFailed((e) -> {
// eventual error handling by catching exceptions from task.get()
});
new Thread(task).start();
I assumed Java 8 and the possibility to use Lambda expressions. Of course it is possible without them.
You are better off making use of concurrency mechanisms/Worker interfaces in JavaFx - Tasks and services instead of using Platform.runLater(). The tasks and services allow you to manage the long running tasks in a separate thread. They also provide callbacks to indicate the progress of the tasks.
You could explore further at http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm
Also have a look at the Ensemble JavaFX samples for Tasks and Services - http://www.oracle.com/technetwork/java/javase/overview/javafx-samples-2158687.html
I am trying to figure out a clean and simple way to obtain the uid resulting from a call to createUser() when working with the Java SDK. This is easy to do when working with the Javascript SDK (e.g., this question/answer). I've also seen the question raised on Stackoverflow in the context of the Firebase iOS API where it apparently isn't so easy. My problem is how to do it using the Firebase Java SDK. Specifically, my use case is the same as that in the iOS-related question, i.e. allow an Admin user to create user accounts (email/password authentication) and also store other info about the created user in Firebase with the uid as the key. Knowing and using the uid as a key is essential in that it is the basis for the security rules.
I've seen a couple of proposed solutions, both of which involved some procedure to be carried out after the new user account has been created. These are
query the Firebase using the email address
Login as the new user and use the authData to get the uid
Either way I have a convoluted solution with multiple async callbacks to deal with an issue that is trivial when using the Javascript API.
I therefore have three specific questions:
Is there currently a better approach than the two I've listed above?
If I use the 2nd approach and login as the newly created user, doesn't that over-ride the Admin token (i.e., log-out the admin who created the user) which in turn means new security rules apply?
Is there any expectation that the Android & Java SDK's will be upgraded anytime soon so that the createUser() API is the same as the Javascript version?
UPDATE: Digging deeper and experimenting a bit I found the answers to my questions. It turns out that the API documentation provided by Firebase is out of date and/or inconsistent.
Re Q1: According to the Javadoc for createUser() the the only available callback handler is a Firebase.ResultHandler. However according to the Changelog, the API Reference document, and the documentation on Creating User Accounts, a Firebase.ValueResultHandler may be used as well. This provides direct access to the UID
Re Q2: The answer is yes. Authenticating the newly created user account results in the replacement of the auth token.
Re Q3: The real question should be "When are the Firebase folks going to update the Javadoc?" Or maybe a better question is "Why are new versions of the SDK being released without updated and accurate documentation?"
The following code is the correct way to deal with creating a new user
Firebase ref = new Firebase("https://<YOUR-FIREBASE>.firebaseio.com");
ref.createUser("harry#foo.com", "badPassword", new Firebase.ValueResultHandler<Map<String, Object>>() {
public void onSuccess(Map<String, Object> result) {
System.out.println("New account with uid: " + result.get("uid"));
}
public void onError(FirebaseError firebaseError) {
// there was an error
}
});
I've updated the question to explain the reasons.
Try this. This is for the newer version of Firebase that came out in the most recent Google I/O. I am not promoting this new version or putting the older version down. I am just stating this as an alternative to the solution above:
mAuth = FirebaseAuth.getInstance();
//creates the user with email and password...make this another type of login if you want
mAuth.createUserWithEmailAndPassword(mEmail, mPassword).addOnCompleteListener(signup.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
//do something
}
}
});
Now you can add an AuthStateListener. You will have to put code in the onCreate, onStart, and onStop methods. Note that the above code can go in any reasonable method (e.g. onCreate, onStart, onResume, etc.). Here we go:
FirebaseAuth mAuth;
FirebaseAuth.AuthStateListener mAuthListener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_something);
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if(user != null){
//check for null to prevent NullPointerException when dealing with user
if(!user.getUid().matches("")){
//make this check just in case...I've experienced unexplainable glitches here
String uid = user.getUid();
//do more stuff with Uid
}
}
}
}
}
#Override
public void onStart(){
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
#Override
public void onStop(){
super.onStop();
if(mListener != null){
mAuth.removeAuthStateListener(mAuthListener);
}
}
In the end, what happens is, once the user is created (and signed in at the same time), the mAuthListener makes a callback (it executes whatever is inside the mAuthListener, which, in this case, is getting the user's UID and doing other stuff with it). If you need help with this new Firebase in Android, here is a link to help you out: https://firebase.google.com/docs/android/setup
I have developed and released one application in market long ago. Now some some users pointed crashes when holding application for long time. Now I identified the reason for the crash, that is I am using a class with static variable and methods to store data (getters and setters). Now I want to replace the static way with any other ways.From my study I got the following suggestions:
shared preferences: I have to store more than 40 variable (strings, int and json arrays and objects), So I think using shared preferences is not a good idea.
SQLite: more than 40 fields are there and I don't need to keep more than one value at a time.I am getting values for fields from different activities. I mean name from one activity , age from another activity, etc So using SQLite also not a good Idea I think.
Application classes: Now I am thinking about using application classes to store these data. Will it loss the data like static variable after hold the app for long time?
Now I replace the static variable with application class . Please let me know that application data also became null after long time?
It may useful to somebody.
Even though I didn't get a solution for my problem, I got the reason for why shouldn't we use application objects to hold the data. Please check the below link
Don't use application object to store data
Normally if you have to keep something in case your Activity gets destroyed you save all these things in onSaveInstanceState and restore them in onCreate or in onRestoreInstanceState
public class MyActivity extends Activity {
int myVariable;
final String ARG_MY_VAR="myvar";
public void onCreate(Bundle savedState) {
if(savedState != null {
myVariable = savedState.getInt(ARG_MY_VAR);
} else {
myVariable = someDefaultValue;
}
public void onSaveInstanceState(Bundle outState) {
outState.putInt(ARG_MY_VAR, myVariable);
super.onSaveInstanceState(outState);
}
}
Here if Android OS destroys your Activity onSaveInstanceState will be called and your important variable will be saved. Then when the user returns to your app again Android OS restores the activity and your variable will be correctly initialized
This does not happen when you call finish() yourself though, it happens only when Android destroys your activity for some reasons (which is quite likely to happen anytime while your app is in background).
First you should overwrite the onSaveInstanceState and onRestoreInstanceState methods in you activity:
#Override
protected void onSaveInstanceState (Bundle outState){
outState.putString("myVariable", myVariable);
// Store all you data inside the bundle
}
#Override
protected void onRestoreInstanceState (Bundle savedInstanceState){
if(savedInstanceState != null){
myVariable = savedInstanceState.getString("myVariable");
// Restore all the variables
}
}
May be try use static variable inside Application space?
public class YourApplication extends Application
{
private static ApplicationBubblick singleton;
public String str;
public static YourApplication getInstance()
{
return singleton;
}
}
And use variable via:
YourApplication.getInstance().str = ...; // set variable
... = YourApplication.getInstance().str; // get variable
This variable will be live until your app will start and stop all services or activities of your app. This is not work when your app crash.