How to edit SharedPreferences without blocking UI Thread? - android-asynctask

I want to put many values in SharedPreferences but doing so is blocking my UI thread. I tried to do it in ASyncTask's doInBackground() and also by using a Handler, but both attempts turned out to be of no use.
Here's the method:
....
Context c = RamadanWidgetConfig.this;
savedDataSehri = c.getSharedPreferences("Sehri", 0);
savedDataIftar = c.getSharedPreferences("Iftar", 0);
boolean sFilled = savedDataSehri.getBoolean("filled", false);
boolean iFilled = savedDataIftar.getBoolean("filled", false);
if (!sFilled || !iFilled) {
fillSharedPreferences();
} ....
private void fillSharedPreferences() {
String date[] = {"6/18/2015", "6/19/2015", "6/20/2015", "6/21/2015", "6/22/2015", "6/23/2015", "6/24/2015", "6/25/2015", "6/26/2015", "6/27/2015", "6/28/2015", "6/29/2015", "6/30/2015", "7/1/2015", "7/2/2015", "7/3/2015", "7/4/2015", "7/5/2015", "7/6/2015", "7/7/2015", "7/8/2015", "7/9/2015", "7/10/2015", "7/11/2015", "7/12/2015", "7/13/2015", "7/14/2015", "7/15/2015", "7/16/2015", "7/17/2015"};
String sehri[] = {"4:13 AM", "4:13 AM", "4:14 AM", "4:14 AM", "4:14 AM", "4:14 AM", "4:15 AM", "4:15 AM", "4:15 AM", "4:15 AM", "4:16 AM", "4:16 AM", "4:17 AM", "4:17 AM", "4:17 AM", "4:18 AM", "4:18 AM", "4:19 AM", "4:19 AM", "4:20 AM", "4:20 AM", "4:21 AM", "4:21 AM", "4:22 AM", "4:22 AM", "4:23 AM", "4:24 AM", "4:24 AM", "4:25 AM", "4:26 AM"};
String iftar[] = {"7:24 PM", "7:25 PM", "7:25 PM", "7:25 PM", "7:25 PM", "7:25 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:26 PM", "7:25 PM", "7:25 PM", "7:25 PM", "7:25 PM", "7:24 PM"};
SharedPreferences.Editor editorSehri = savedDataSehri.edit();
SharedPreferences.Editor editorIftar = savedDataIftar.edit();
for (int i = 0; i < date.length; i++) {
editorSehri.putString(date[i], sehri[i]);
editorIftar.putString(date[i], iftar[i]);
}
editorSehri.putBoolean("filled", true);
editorIftar.putBoolean("filled", true);
editorSehri.apply();
editorIftar.apply();
}
Basically, I am adding a widget to home screen and before adding it I am checking if I have the data or not. This method gets called if I don't have the data. If this does not get called then the other code executes within milliseconds.
EDIT: Actually I found out that problem lies somewhere else. I was clearing data of app before adding the widget to clear SharedPreferences, but I later found out that clearing data also clears something else which is related to the first launch of the app. The app always takes long while launching for the first time. Perhaps it is setting things up, but I don't exactly know what's going on. So after clearing the data and then adding the widget, the app essentially launched for the first time. This is why it was slowing down and I thought that SharedPreferences was making it slow.
Now I need to figure out why the app takes so long in its first launch and how to avoid it. (Splash screen comes first to my mind).

Not clear what part is responsible for populating data. Generally SharedPreferences is thread safe, but doesn't support use across multiple processes.
With a cold start (no data) how do you wait result? Constant checking still can block UI, even if you use threading to insert data.
If you use a huge amount of structured data set consider to use SQLite.
To populate data you may use service.

Related

How to display all time slots between two times

I have a Laravel application in which I need to display all time slots between 9AM to 3AM on the basis of 15 minutes interval.
the time slots does not contain no date, only times format like (AM and PM)
you carbon CarbonPeriod
use Carbon\CarbonPeriod;
$period = new CarbonPeriod('03:00', '15 minutes', '14:00'); // for create use 24 hours format later change format
$slots = [];
foreach($period as $item){
array_push($slots,$item->format("h:i A"));
}
return $slots;
as per your req. you need to use like this
$today = today()->format('Y-m-d') . " 2:00 PM";
$tomorrow = today()->addDays('1')->format('Y-m-d') . " 3:00 AM";
$period = new CarbonPeriod(new Carbon($today), '15 minutes', new Carbon($tomorrow));
$slots = [];
foreach ($period as $item) {
array_push($slots, $item->format("h:i A"));
}
it retrun
[
"02:00 PM",
"02:15 PM",
"02:30 PM",
"02:45 PM",
"03:00 PM",
"03:15 PM",
"03:30 PM",
"03:45 PM",
"04:00 PM",
"04:15 PM",
"04:30 PM",
"04:45 PM",
"05:00 PM",
"05:15 PM",
"05:30 PM",
"05:45 PM",
"06:00 PM",
"06:15 PM",
"06:30 PM",
"06:45 PM",
"07:00 PM",
"07:15 PM",
"07:30 PM",
"07:45 PM",
"08:00 PM",
"08:15 PM",
"08:30 PM",
"08:45 PM",
"09:00 PM",
"09:15 PM",
"09:30 PM",
"09:45 PM",
"10:00 PM",
"10:15 PM",
"10:30 PM",
"10:45 PM",
"11:00 PM",
"11:15 PM",
"11:30 PM",
"11:45 PM",
"12:00 AM",
"12:15 AM",
"12:30 AM",
"12:45 AM",
"01:00 AM",
"01:15 AM",
"01:30 AM",
"01:45 AM",
"02:00 AM",
"02:15 AM",
"02:30 AM",
"02:45 AM",
"03:00 AM"
]
ref link https://carbon.nesbot.com/docs/#api-period
Here is a framework agnostic function
/**
* get a list of hours btw two range
*
* #param int $lower start hours in secondes
* #param int $upper end hours in secondes
* #param int $step hop btw hours in seconde
* #param null $format output hours format
*
* #return array with hours range interval
* Exemple of use: // Every 30 Minutes from 8 AM - 5 PM, using Custom Time Format: hoursRange( 28800, 61200, 60 * 30, 'h:i a' );
*/
function hoursRange($lower = 0, $upper = 86400, $step = 1800, $format = 'H:i')
{
$times = [];
if (empty($format))
{
$format = 'H:i';
}
foreach (range($lower, $upper, $step) as $increment)
{
$increment = gmdate('H:i', $increment);
list($hour, $minutes) = explode(':', $increment);
$date = new \DateTime($hour.':'.$minutes);
$times[(string)$increment] = $date->format($format);
}
return $times;
}
Example of use with output:
hoursRange(0, 86400, 1800, 'H:i')
array:48 [▼
"00:00" => "00:00"
"00:30" => "00:30"
"01:00" => "01:00"
"01:30" => "01:30"
"02:00" => "02:00"
"02:30" => "02:30"
"03:00" => "03:00"
"03:30" => "03:30"
"04:00" => "04:00"
"04:30" => "04:30"
"05:00" => "05:00"
"05:30" => "05:30"
"06:00" => "06:00"
"06:30" => "06:30"
"07:00" => "07:00"
"07:30" => "07:30"
"08:00" => "08:00"
"08:30" => "08:30"
"09:00" => "09:00"
"09:30" => "09:30"
"10:00" => "10:00"
"10:30" => "10:30"
"11:00" => "11:00"
"11:30" => "11:30"
"12:00" => "12:00"
"12:30" => "12:30"
"13:00" => "13:00"
"13:30" => "13:30"
//etc .......
]

Daterangepicker dates are wrong

I am using this daterangepicker https://www.daterangepicker.com/ but somehow it displays wrong dates.
For example: Today it is the Sunday, 22th November 2020, but the daterangepicker says the 22th Novemeber 2020 is a Monday.
Example
and here is my configuration:
$('#singledaterange').daterangepicker({
"locale": {
"format": "D. MMM YYYY",
"separator": " - ",
"applyLabel": "OK",
"cancelLabel": "Abbrechen",
"fromLabel": "Von",
"toLabel": "Bis",
"weekLabel": "W",
"daysOfWeek": [
"Mo",
"Di",
"Mi",
"Do",
"Fr",
"Sa",
"So"
],
"monthNames": [
"Januar",
"Februar",
"März",
"April",
"Mai",
"Juni",
"Juli",
"August",
"September",
"Oktober",
"November",
"Dezember"
],
"firstDay": 0
},
"minDate": moment(),
});
I solved it. It was obviously my fault.
By default, Sunday is the first day of the week, so I had to put Sunday first in the daysOfWeek array, not Monday.

How to show next time slots from the current time

I am trying to show next time slots from the current time.
Table contains the time slots 'time' = 12:00 AM, 10:00 AM, 12:00 PM, 02:00 PM, 05:00 PM, 08:00 PM, 10:00 PM
I just want to show the upcoming time slots from the current time. The time slots remaining for today will show in today array and the next time slots in tomorrow array.
$now = Carbon::now()->format('g:i A');
$time = TimeSlot::where('time', '<', $now)->get();
$data = array('message'=>ResponseMessage::statusResponses(ResponseMessage::_STATUS_DATA_FOUND), 'timeSlots'=>$time, 'current_time'=>$now);
return $this->sendSuccessResponse($data);
Output is :
{
"message": "Data retrieve Successfully",
"timeSlots": [
{
"id": 1,
"time": "12:00 AM"
},
{
"id": 2,
"time": "10:00 AM"
},
{
"id": 3,
"time": "12:00 PM"
},
{
"id": 4,
"time": "02:00 PM"
},
{
"id": 5,
"time": "05:00 PM"
},
{
"id": 6,
"time": "08:00 PM"
},
{
"id": 7,
"time": "10:00 PM"
}
],
"current_time": "5:16 PM",
"status": true
}
Reuired Output will be something like this:
{
"message": "Data retrieve Successfully",
"timeSlots": [
{
"today": [
{
"id": 6,
"time": "08:00 PM"
},
{
"id": 7,
"time": "10:00 PM"
}
],
"tomorrow": [
{
"id": 1,
"time": "12:00 AM"
},
{
"id": 2,
"time": "10:00 AM"
},
{
"id": 3,
"time": "12:00 PM"
},
{
"id": 4,
"time": "02:00 PM"
},
{
"id": 5,
"time": "05:00 PM"
}
],
}
],
"current_time": "5:16 PM",
"status": true
}
Please help me out,
In case you can't modify your table to store info in a more useful way (as suggested in my comment), you can do at the collection level. For this, I'm making use of the map() and partition() collection methods. Given that the first method returns the same collection instance, it allows us to chain the methods.
list($tomorrow, $today) = TimeSlot::all()
// Here we create a new field that will contain a carbon instance of the time
->map(function ($slot) {
$slot['timeTemp'] = Carbon::createFromFormat('g:i A', $slot['time']);
return $slot;
})
// Then we partition the collection using the current time,
// this will return two collections
->partition(function ($slot) {
return $slot['timeTemp'] < now();
});
$timeSlots = [
'today' => $today,
'tomorrow' => $tomorrow,
];
$data = [
'message' => ResponseMessage::statusResponses(ResponseMessage::_STATUS_DATA_FOUND),
'timeSlots' => $timeSlots,
'current_time' => Carbon::now()->format('g:i A'),
];
return $this->sendSuccessResponse($data);
Of course, this will also return the 'timeTemp' value that we inserted in each time slot, but you can ignore them or remove them by mapping through each slot again. Up to you.

aggregate data and still use changefeed in rethinkDB

I'm enjoying learning reQL so far but I stumbled upon a problem.
This is the data that I have stored in a table called events
[{
"date": "Tue Mar 17 2015 00:00:00 GMT+00:00" ,
"id": "00dacebd-b27e-49b5-be4b-42c2578db4bb" ,
"event_name": "View page" ,
"total": 4 ,
"unique": 4
},
{
"date": "Mon Mar 16 2015 00:00:00 GMT+00:00" ,
"id": "09ac3579-960b-4a2b-95be-8e018d683494" ,
"event_name": "View page" ,
"total": 68 ,
"unique": 35
},
{
"date": "Tue Mar 17 2015 00:00:00 GMT+00:00" ,
"id": "0bb01050-e93d-4845-94aa-b86b1198338d" ,
"event_name": "Click" ,
"total": 17 ,
"unique": 8
},
{
"date": "Mon Mar 16 2015 00:00:00 GMT+00:00" ,
"id": "174dcf3e-7c77-47b6-a05d-b875c9f7e563" ,
"event_name": "Click" ,
"total": 113 ,
"unique": 35
}]
And I would like the end result to look like this
[{
"date": "Mon Mar 16 2015 00:00:00 GMT+00:00",
"Click": 113,
"View Page": 68
},
{
"date": "Tue Mar 17 2015 00:00:00 GMT+00:00",
"Click": 17,
"View Page": 4
}]
The closet I got was with this query:
r.table("events").orderBy({index: r.desc('date')}).group('date').map(function(event) {
return r.object(event('repo_name'), event('unique'));
}).reduce(function(a, b) {
return a.merge(b.keys().map(function(key) {
return [key, a(key).default(0).add(b(key))];}).coerceTo('object'));
})
The results is:
[{
"date": "Mon Mar 16 2015 00:00:00 GMT+00:00",
"reduction": {
"Click": 113,
"View page": 68
}
},
{
"group": "Tue Mar 17 2015 00:00:00 GMT+00:00",
"reduction": {
"Click": 17,
"View page": 4
}
}]
However as you can see the events are nested under reduction and changefeeds won't work on this query either :(
Anyone can point me in the right direction?
Cheers,
You can change the group/reduction format like this:
query.ungroup().map(function(row){
return r.expr({date: row('group')}).merge(row('reduction'));
})
Unfortunately changefeeds on aggregations aren't supported as of 1.6, but that should be possible in 2.2 or 2.3 (so in a few months).

Using Ruby to retrieve ids from JSON response [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am building an application using Ruby 2.0 where after parsing a string to JSON, I'm interested in retrieving all of the game_id fields listed below. After parsing has been completed, is there a trivial way in Ruby to map/collect through the parsed JSON response to do that? Here's an example of the JSON I'm working with.
{
"season_type"=>"Regular",
"sport"=>"NBA",
"gamedate"=>"11/29/2013",
"updated_at"=>"2013-11-29 23:35:17 UTC",
"games"=>[
{
"game"=>{
"home_team_name"=>"Charlotte",
"game_id"=>19089,
"visiting_team_name"=>"Milwaukee",
"home_team_id"=>152,
"gametime"=>"07:00 PM",
"visiting_team_id"=>103
}
},
{
"game"=>{
"home_team_name"=>"Orlando",
"game_id"=>19091,
"visiting_team_name"=>"San Antonio",
"home_team_id"=>117,
"gametime"=>"07:00 PM",
"visiting_team_id"=>110
}
},
{
"game"=>{
"home_team_name"=>"Toronto",
"game_id"=>19092,
"visiting_team_name"=>"Miami",
"home_team_id"=>118,
"gametime"=>"07:00 PM",
"visiting_team_id"=>115
}
},
{
"game"=>{
"home_team_name"=>"Atlanta",
"game_id"=>19096,
"visiting_team_name"=>"Dallas",
"home_team_id"=>91,
"gametime"=>"07:30 PM",
"visiting_team_id"=>95
}
},
{
"game"=>{
"home_team_name"=>"Boston",
"game_id"=>19101,
"visiting_team_name"=>"Cleveland",
"home_team_id"=>92,
"gametime"=>"07:30 PM",
"visiting_team_id"=>94
}
},
{
"game"=>{
"home_team_name"=>"Detroit",
"game_id"=>19104,
"visiting_team_name"=>"LA Lakers",
"home_team_id"=>97,
"gametime"=>"07:30 PM",
"visiting_team_id"=>102
}
},
{
"game"=>{
"home_team_name"=>"Houston",
"game_id"=>19106,
"visiting_team_name"=>"Brooklyn",
"home_team_id"=>99,
"gametime"=>"08:00 PM",
"visiting_team_id"=>104
}
},
{
"game"=>{
"home_team_name"=>"Indiana",
"game_id"=>19110,
"visiting_team_name"=>"Washington",
"home_team_id"=>100,
"gametime"=>"08:00 PM",
"visiting_team_id"=>113
}
},
{
"game"=>{
"home_team_name"=>"Oklahoma City",
"game_id"=>19108,
"visiting_team_name"=>"Golden State",
"home_team_id"=>111,
"gametime"=>"08:00 PM",
"visiting_team_id"=>98
}
},
{
"game"=>{
"home_team_name"=>"Philadelphia",
"game_id"=>19112,
"visiting_team_name"=>"New Orleans",
"home_team_id"=>106,
"gametime"=>"08:00 PM",
"visiting_team_id"=>114
}
},
{
"game"=>{
"home_team_name"=>"Denver",
"game_id"=>19116,
"visiting_team_name"=>"New York",
"home_team_id"=>96,
"gametime"=>"09:00 PM",
"visiting_team_id"=>105
}
},
{
"game"=>{
"home_team_name"=>"Utah",
"game_id"=>19119,
"visiting_team_name"=>"Phoenix",
"home_team_id"=>112,
"gametime"=>"09:00 PM",
"visiting_team_id"=>107
}
},
{
"game"=>{
"home_team_name"=>"Sacramento",
"game_id"=>19123,
"visiting_team_name"=>"LA Clippers",
"home_team_id"=>109,
"gametime"=>"10:00 PM",
"visiting_team_id"=>101
}
}
]
}
Simple:
parsed_json['games'].map { |g| g['game']['game_id'] }

Resources