问:
Using AVAudioEngine to schedule sounds for low-latency metronome
I am creating a metronome as part of a larger app and I have a few very short wav files to use as the individual sounds. I would like to use AVAudioEngine because NSTimer has significant latency problems and Core Audio seems rather daunting to implement in Swift. I'm attempting the following, but I'm currently unable to implement the first 3 steps and I'm wondering if there is a better way.

Code outline:

Create an array of file URLs according to the metronome's current settings (number of beats per bar and subdivisions per beat; file A for beats, file B for subdivisions)

Programmatically create a wav file with the appropriate number of frames of silence, based on the tempo and the length of the files, and insert it into the array between each of the sounds

Read those files into a single AudioBuffer or AudioBufferList

audioPlayer.scheduleBuffer(buffer, atTime:nil, options:.Loops, completionHandler:nil)

So far I have been able to play a looping buffer (step 4) of a single sound file, but I haven't been able to construct a buffer from an array of files or create silence programmatically, nor have I found any answers on StackOverflow that address this. So I'm guessing that this isn't the best approach.

My question is: Is it possible to schedule a sequence of sounds with low latency using AVAudioEngine and then loop that sequence? If not, which framework/approach is best suited for scheduling sounds when coding in Swift?

答:
To expand upon 5hrp's answer:

Take the simple case where you have two beats, an upbeat (tone1) and a downbeat (tone2), and you want them out of phase with each other so the audio will be (up, down, up, down) to a certain bpm.

You will need two instances of AVAudioPlayerNode (one for each beat), let's call them audioNode1 and audioNode2

The first beat you will want to be in phase, so setup as normal:

```<code>let buffer = tickBuffer(forBpm: bpm)
audioNode1player.scheduleBuffer(buffer, atTime: nil, options: .loops, completionHandler: nil)
</code>```

then for the second beat you want it to be exactly out of phase, or to start at t=bpm/2. for this you can use an AVAudioTime variable:

```<code>audioTime2 = AVAudioTime(sampleTime: AVAudioFramePosition(AVAudioFrameCount(audioFile2.processingFormat.sampleRate * 60 / Double(bpm) * 0.5)), atRate: Double(1))
</code>```

you can use this variable in the buffer like so:

```<code>audioNode2player.scheduleBuffer(buffer, atTime: audioTime2, options: .loops, completionHandler: nil)
</code>```

This will play on loop your two beats, bpm/2 out of phase from each other!

It's easy to see how to generalise this to more beats, to create a whole bar. It's not the most elegant solution though, because if you want to say do 16th notes you'd have to create 16 nodes.

Body:
To expand upon 5hrp's answer:

Take the simple case where you have two beats, an upbeat (tone1) and a downbeat (tone2), and you want them out of phase with each other so the audio will be (up, down, up, down) to a certain bpm.

You will need two instances of AVAudioPlayerNode (one for each beat), let's call them audioNode1 and audioNode2

The first beat you will want to be in phase, so setup as normal:

let buffer = tickBuffer(forBpm: bpm)
audioNode1player.scheduleBuffer(buffer, atTime: nil, options: .loops, completionHandler: nil)

then for the second beat you want it to be exactly out of phase, or to start at t=bpm/2. for this you can use an AVAudioTime variable:

audioTime2 = AVAudioTime(sampleTime: AVAudioFramePosition(AVAudioFrameCount(audioFile2.processingFormat.sampleRate * 60 / Double(bpm) * 0.5)), atRate: Double(1))

you can use this variable in the buffer like so:

audioNode2player.scheduleBuffer(buffer, atTime: audioTime2, options: .loops, completionHandler: nil)

This will play on loop your two beats, bpm/2 out of phase from each other!

It's easy to see how to generalise this to more beats, to create a whole bar. It's not the most elegant solution though, because if you want to say do 16th notes you'd have to create 16 nodes.


来源: stackexchange

问:
Dependency Injection fails with MVC5 and Ninject
I'm trying to inject a couple of classes in a controller, but I'm failing.

This is what I've done:

Added Ninject.Web.WebApi.WebHost and WebActivatorEx NuGet packages

Created the following class under App_Start:

NinjectWebCommon.cs

```<code>using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.Common.WebHost;
using MyProject;
using MyProject.Models;
using MyProject.Classes;
using System;
using System.Web;

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(NinjectWebCommon), "Stop")]

namespace MyProject
{
    public static class NinjectWebCommon
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        public static void Start()
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }

        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IMyContext>().ToSelf().InRequestScope();
            kernel.Bind<IErp>().ToSelf().InRequestScope();
        }
    }
}
</code>```

Created my classes:

MyContext.cs:

```<code>using MyProject.Models;
using System;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Threading.Tasks;

namespace MyProject.Models
{
    public interface IMyContext : IDisposable
    {
        DbSet<Operator> Operators { get; set; }
        Task<int> SaveChangesAsync();
    }

    public class MyContext : DbContext, IMyContext
    {
        public MyContext () : base("MyContext ") { }
        public DbSet<Operator> Operators { get; set; }
        public async override Task<int> SaveChangesAsync()
        {
            return await SaveChangesAsync(CancellationToken.None);
        }
    }
}
</code>```

Erp.cs

```<code>public interface IErp
{
    Task ImportListAsync();
}

public class Erp : IErp
{
    private readonly IMyContext _context;
    public Erp(IMyContext context)
    {
        _context = context;
    }

    public async Task ImportListAsync()
    {
        // do something
    }
}
</code>```

Created a Controller

```<code>using MyProject.Classes;
using MyProject.Models;
using System.Data.Entity;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace MyProject.Controllers
{
    public class OperatorsController : Controller
    {
        private readonly IMyContext _context;
        private readonly IErp _erp;

        public OperatorsController(IMyContext context, Erp Ierp)
        {
            _context = context;
            _erp = erp;
        }

        // GET: Operators
        public async Task<ActionResult> Index()
        {
            return View(await _context.Operators.ToListAsync());
        }

        // GET: Operators/Import
        public async Task<ActionResult> Import()
        {
            await _erp.ImportListAsync();
            return View("Index", await _context.Operators.ToListAsync());
        }
    }
}
</code>```

But when I run the application I still get the infamous error about the missing of parameterless constructor. This says to me that DI is not working.

答:
I believe your registration calls in RegisterServices are wrong - you cannot bind an interface .ToSelf() - you need to bind the interface to the concrete class that implements it - something like this:

```<code>private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IMyContext>().To<MyContext>().InRequestScope();
    kernel.Bind<IErp>().To<Erp>().InRequestScope();
}
</code>```

With this, you tell the DI container to instantiate an MyContext class whenever in your code you're expecting an IMyContext dependency

ContentLicense: CC BY-SA 3.0

Body:
I'm trying to inject a couple of classes in a controller, but I'm failing.

This is what I've done:

Added Ninject.Web.WebApi.WebHost and WebActivatorEx NuGet packages

Created the following class under App_Start:

NinjectWebCommon.cs

using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using Ninject.Web.Common.WebHost;
using MyProject;
using MyProject.Models;
using MyProject.Classes;
using System;
using System.Web;

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(NinjectWebCommon), "Stop")]

namespace MyProject
{
    public static class NinjectWebCommon
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        public static void Start()
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
            kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

            RegisterServices(kernel);
            return kernel;
        }

        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IMyContext>().ToSelf().InRequestScope();
            kernel.Bind<IErp>().ToSelf().InRequestScope();
        }
    }
}

Created my classes:

MyContext.cs:

using MyProject.Models;
using System;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Threading.Tasks;

namespace MyProject.Models
{
    public interface IMyContext : IDisposable
    {
        DbSet<Operator> Operators { get; set; }
        Task<int> SaveChangesAsync();
    }

    public class MyContext : DbContext, IMyContext
    {
        public MyContext () : base("MyContext ") { }
        public DbSet<Operator> Operators { get; set; }
        public async override Task<int> SaveChangesAsync()
        {
            return await SaveChangesAsync(CancellationToken.None);
        }
    }
}

Erp.cs

public interface IErp
{
    Task ImportListAsync();
}

public class Erp : IErp
{
    private readonly IMyContext _context;
    public Erp(IMyContext context)
    {
        _context = context;
    }

    public async Task ImportListAsync()
    {
        // do something
    }
}

Created a Controller

using MyProject.Classes;
using MyProject.Models;
using System.Data.Entity;
using System.Threading.Tasks;
using System.Web.Mvc;

namespace MyProject.Controllers
{
    public class OperatorsController : Controller
    {
        private readonly IMyContext _context;
        private readonly IErp _erp;

        public OperatorsController(IMyContext context, Erp Ierp)
        {
            _context = context;
            _erp = erp;
        }

        // GET: Operators
        public async Task<ActionResult> Index()
        {
            return View(await _context.Operators.ToListAsync());
        }

        // GET: Operators/Import
        public async Task<ActionResult> Import()
        {
            await _erp.ImportListAsync();
            return View("Index", await _context.Operators.ToListAsync());
        }
    }
}

But when I run the application I still get the infamous error about the missing of parameterless constructor. This says to me that DI is not working.

Body:
I believe your registration calls in RegisterServices are wrong - you cannot bind an interface .ToSelf() - you need to bind the interface to the concrete class that implements it - something like this:

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IMyContext>().To<MyContext>().InRequestScope();
    kernel.Bind<IErp>().To<Erp>().InRequestScope();
}

With this, you tell the DI container to instantiate an MyContext class whenever in your code you're expecting an IMyContext dependency


问:
JOIN Table no duplicate column
I have 4 tables like this

Student Table

```<code>-----------------------
|id_student | name    |
|1          | John    |
|2          | Michael |
-----------------------
</code>```

Phone Number Table

```<code>--------------------------------------
|id_phone | phone_number | id_student |
| 1       |  +612823888  | 1          |
| 2       |  +612823723  | 1          |
| 3       |  +612123123  | 2          |
| 4       |  +613432322  | 2          |
---------------------------------------
</code>```

Course Table

```<code>____________________
|id_course | course  |
|1         | Math    |
|2         | Science |
|3         | Art     |
|__________|_________|
</code>```

Take Course Table

```<code>__________________________________
|id_take | id_student | id_course |
|1       | 1          | 1         |
|2       | 1          | 2         |
|3       | 1          | 3         |
|4       | 2          | 1         |
|________|____________|___________|
</code>```

=== View I Expected ====

```<code> _________________________________
|name    |phone        |course   |
|John    | +6128238883 | Math    |
|John    | +6128237237 | Science |
|John    | -           | Art     |
|Michael | +612123123  | Math    |
|Michael | +613432322  | -       |
|________|_____________|_________|
</code>```

SQL syntax I create :

```<code>SELECT student.name, phone.phone_number, course.course_name FROM student
JOIN phone ON phone.id_student = student.id_student
JOIN take_course ON take_course.id_student = student.id_student
JOIN course ON course.id_course = take_course.id_course
</code>```

There is problem when JOIN Table, because phone_number table just JOIN to student_table and will duplicate in table I expected. What is right SQL Syntax to create view like that?

答:
Use row_number() to generate a sequence ID and then use FULL OUTER JOIN on phone and take-course/course ON id_student & the "sequence id"</p>

```<code>select  s.name, pc.phone_number, pc.course
from    Student s
        inner join
        (
            select  id_student  = coalesce(p.id_student, c.id_student),
                    p.phone_number,
                    c.course
            from
            (
                select  p.id_student, p.phone_number,
                        -- id is the new sequence id
                        id = row_number() over (partition by p.id_student
                                                    order by p.id_phone)
                from    Phone_Number p
            ) p
            full outer join
            (
                select  t.id_student, c.course,
                        -- id is the new sequence id
                        id = row_number() over (partition by t.id_student
                                                    order by c.id_course)
                from    Take_Course t
                        inner join Course c on  t.id_course  = c.id_course
            ) c                             on  p.id_student = c.id_student
                                            and p.id         = c.id
        ) pc                                on  s.id_student = pc.id_student
order by s.name
</code>```

Title: JOIN Table no duplicate column

Body:
I have 4 tables like this

Student Table

-----------------------
|id_student | name    |
|1          | John    |
|2          | Michael |
-----------------------

Phone Number Table

--------------------------------------
|id_phone | phone_number | id_student |
| 1       |  +612823888  | 1          |
| 2       |  +612823723  | 1          |
| 3       |  +612123123  | 2          |
| 4       |  +613432322  | 2          |
---------------------------------------

Course Table

____________________
|id_course | course  |
|1         | Math    |
|2         | Science |
|3         | Art     |
|__________|_________|

Take Course Table

__________________________________
|id_take | id_student | id_course |
|1       | 1          | 1         |
|2       | 1          | 2         |
|3       | 1          | 3         |
|4       | 2          | 1         |
|________|____________|___________|

=== View I Expected ====

 _________________________________
|name    |phone        |course   |
|John    | +6128238883 | Math    |
|John    | +6128237237 | Science |
|John    | -           | Art     |
|Michael | +612123123  | Math    |
|Michael | +613432322  | -       |
|________|_____________|_________|

SQL syntax I create :

SELECT student.name, phone.phone_number, course.course_name FROM student
JOIN phone ON phone.id_student = student.id_student
JOIN take_course ON take_course.id_student = student.id_student
JOIN course ON course.id_course = take_course.id_course

There is problem when JOIN Table, because phone_number table just JOIN to student_table and will duplicate in table I expected. What is right SQL Syntax to create view like that?

Body:
Use row_number() to generate a sequence ID and then use FULL OUTER JOIN on phone and take-course/course ON id_student & the "sequence id"

select  s.name, pc.phone_number, pc.course
from    Student s
        inner join
        (
            select  id_student  = coalesce(p.id_student, c.id_student),
                    p.phone_number,
                    c.course
            from
            (
                select  p.id_student, p.phone_number,
                        -- id is the new sequence id
                        id = row_number() over (partition by p.id_student
                                                    order by p.id_phone)
                from    Phone_Number p
            ) p
            full outer join
            (
                select  t.id_student, c.course,
                        -- id is the new sequence id
                        id = row_number() over (partition by t.id_student
                                                    order by c.id_course)
                from    Take_Course t
                        inner join Course c on  t.id_course  = c.id_course
            ) c                             on  p.id_student = c.id_student
                                            and p.id         = c.id
        ) pc                                on  s.id_student = pc.id_student
order by s.name


问:
problem with sizeof operator
As i want to find array size dynamically in function, i used sizeof operator. But i got some unexpected result.
here is one demo program to show you, what i want to do.

```<code>//------------------------------------------------------------------------------------------
#include <iostream>

void getSize(int *S1){

    int S_size = sizeof S1/sizeof(int);
    std::cout<<"array size(in function):"<<S_size<<std::endl;
}

int main(){

    int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
    getSize(S);
    std::cout<<"array size:"<<sizeof S/sizeof(int)<<std::endl;
    return 0;
}
//------------------------------------------------------------------------------------------
</code>```

compilation command : g++ demo1.cc -o demo1 {fedora 12}

output:

```<code>array size(in function):2
array size:19
</code>```

please explain ,why this is happening.
what can be done to solve this problem.

答:
You will have to pass the size of the array to the function.

Since you are only passing a pointer to the first element in the array, your function has no information on its actual size.

```<code>void getSize(int *S1, size_t size)
{
    int S_Size = sizeof(*S1) * size;
}
</code>```

This is redundant though, if you think about it :D

ContentLicense: CC BY-SA 2.5

Title: problem with sizeof operator

Body:
As i want to find array size dynamically in function, i used sizeof operator. But i got some unexpected result.
here is one demo program to show you, what i want to do.

//------------------------------------------------------------------------------------------
#include <iostream>

void getSize(int *S1){

    int S_size = sizeof S1/sizeof(int);
    std::cout<<"array size(in function):"<<S_size<<std::endl;
}

int main(){

    int S[]={1,2,3,2,5,6,25,1,6,21,121,36,1,31,1,31,1,661,6};
    getSize(S);
    std::cout<<"array size:"<<sizeof S/sizeof(int)<<std::endl;
    return 0;
}
//------------------------------------------------------------------------------------------

compilation command : g++ demo1.cc -o demo1 {fedora 12}

output:

array size(in function):2
array size:19

please explain ,why this is happening.
what can be done to solve this problem.

Body:
You will have to pass the size of the array to the function.

Since you are only passing a pointer to the first element in the array, your function has no information on its actual size.

void getSize(int *S1, size_t size)
{
    int S_Size = sizeof(*S1) * size;
}

This is redundant though, if you think about it :D


问:
How to create a custom (reusable) feature for filter menus
I have a custom filter that matches the one from the Kendo docs:

https://www.telerik.com/kendo-angular-ui/components/grid/data-operations/filtering/reusable-filter/

```<code>@Component({
    selector: 'my-dropdown-filter',
    template: `
    <kendo-dropdownlist
      [data]="data"
      (valueChange)="onChange($event)"
      [defaultItem]="defaultItem"
      [value]="selectedValue"
      [valuePrimitive]="true"
      [textField]="textField"
      [valueField]="valueField">
    </kendo-dropdownlist>
  `
})
export class DropDownListFilterComponent extends BaseFilterCellComponent {

    public get selectedValue(): any {
        const filter = this.filterByField(this.valueField);
        return filter ? filter.value : null;
    }

    @Input() public filter: CompositeFilterDescriptor;
    @Input() public data: any[];
    @Input() public textField: string;
    @Input() public valueField: string;

    public get defaultItem(): any {
        return {
            [this.textField]: "Select item...",
            [this.valueField]: null
        };
    }

    constructor(filterService: FilterService) {
        super(filterService);
    }

    public onChange(value: any): void {
        this.applyFilter(
            value === null ? // value of the default item
                this.removeFilter(this.valueField) : // remove the filter
                this.updateFilter({ // add a filter for the field with the value
                    field: this.valueField,
                    operator: "eq",
                    value: value
                })
        ); // update the root filter
    }
}
</code>```

It works fine with "row" style grid filters. However, when I try to change it to the "menu" style the filter applies whenever the dropdown is changed. Every other filter in that style requires you to click the "Filter" button. If I change the code in the change handler to:

```<code>public onChange(value: any): void {
    if (value) {
        this.updateFilter({ // add a filter for the field with the value
            field: this.valueField,
            operator: 'eq',
            value: value
        })
    }
    else {
        this.removeFilter(this.valueField);
    }
}
</code>```

Then the filter button feature works as expected; but it doesn't actually filter the grid. I am expecting there to be some method to override that is called when "Filter" is clicked but have had no luck finding it. I've also tried just setting the filter property (same effect) or using applyFilter which just immediately filters again.

How do you use custom filter components with the "menu" style filters in Kendo Angular Grids?

答:
When customizing the Filter menus you need to use the kendoGridFilterMenuTemplate directive (instead of the kendoGridFilterCellTemplate one).

Step-by-step explanation of the process and a runnable example are available in the docs.

Body:
I have a custom filter that matches the one from the Kendo docs:

https://www.telerik.com/kendo-angular-ui/components/grid/data-operations/filtering/reusable-filter/

@Component({
    selector: 'my-dropdown-filter',
    template: `
    <kendo-dropdownlist
      [data]="data"
      (valueChange)="onChange($event)"
      [defaultItem]="defaultItem"
      [value]="selectedValue"
      [valuePrimitive]="true"
      [textField]="textField"
      [valueField]="valueField">
    </kendo-dropdownlist>
  `
})
export class DropDownListFilterComponent extends BaseFilterCellComponent {

    public get selectedValue(): any {
        const filter = this.filterByField(this.valueField);
        return filter ? filter.value : null;
    }

    @Input() public filter: CompositeFilterDescriptor;
    @Input() public data: any[];
    @Input() public textField: string;
    @Input() public valueField: string;

    public get defaultItem(): any {
        return {
            [this.textField]: "Select item...",
            [this.valueField]: null
        };
    }

    constructor(filterService: FilterService) {
        super(filterService);
    }

    public onChange(value: any): void {
        this.applyFilter(
            value === null ? // value of the default item
                this.removeFilter(this.valueField) : // remove the filter
                this.updateFilter({ // add a filter for the field with the value
                    field: this.valueField,
                    operator: "eq",
                    value: value
                })
        ); // update the root filter
    }
}

It works fine with "row" style grid filters. However, when I try to change it to the "menu" style the filter applies whenever the dropdown is changed. Every other filter in that style requires you to click the "Filter" button. If I change the code in the change handler to:

public onChange(value: any): void {
    if (value) {
        this.updateFilter({ // add a filter for the field with the value
            field: this.valueField,
            operator: 'eq',
            value: value
        })
    }
    else {
        this.removeFilter(this.valueField);
    }
}

Then the filter button feature works as expected; but it doesn't actually filter the grid. I am expecting there to be some method to override that is called when "Filter" is clicked but have had no luck finding it. I've also tried just setting the filter property (same effect) or using applyFilter which just immediately filters again.

How do you use custom filter components with the "menu" style filters in Kendo Angular Grids?


问:
How to create real-time push notifications from Telegram Chats to Web API?
I am new to Telegram development and am looking for a way to push real-time notifications from a current group that I am in to my own c# Web API. I was looking at the API docs, but confused about where should i start, Bot or Telegram APIs? Are there any existing projects that show such integration? </p>

答:
It can be achieved using Telegram Bot:

Create a Telegram Bot by contacting @BotFather bot in telegram.

Set a Web-Hook, so that any updates that @YourBot receives are
transmitted by telegram via URL that you provide. It should be a
secured one (HTTPS). You may also use polling. It is all described
here: Telegram Bot Api - getting updates

Now if you add @YourBot to your Group, it will only receive/transmit your
commands (messages that start with '/'). If you want him to
receive/transmit all messages you have to turn off @YourBot's
privacy mode. It is also configured via @BotFather.


问:
checkbox object IF statement does not recognize the variables in MATLAB GUIDE
everyone. Probably, I am making a utterly silly mistake here but here is the problem:

I have made a GUI using MATLAB GUIDE. I added some checkboxes to the GUI so that they will plot something on axes2 if checked and delete it otherwise. In case if you ask, there are going to be other plots so there is hold on and off. It works like this:

```<code>function checkbox1_Callback(hObject, eventdata, handles)
% Hint: get(hObject,'Value') returns toggle state of checkbox1
if get(hObject, 'Value') == 1
    axes(handles.axes2);
    x = handles.x;
    distanceX_Plot = evalin('base', 'CAN2_MPC_C19_Dist_X_VehObj0_Cval_MPC');
    hold on;
    distanceX_Plotted = plot(x,distanceX_Plot, 'r');
    legend('Distance X')
    hold off;
else
    delete(distanceX_Plotted);
end
</code>```

but the distanceX_Plotted in the IF part gets underlined and says variable might be unused and the second distanceX_Plotted in the ELSE statement says that variable may be used before it is defined.

The complete error is like this:

Undefined function or variable 'distanceX_Plotted'.

Error in untitled>checkbox1_Callback (line 224) delete(distanceX_Plotted);

Error in gui_mainfcn (line 95) feval(varargin{:});

Error in untitled (line 42) gui_mainfcn(gui_State, varargin{:});

Error in matlab.graphics.internal.figfile.FigFile/read>@(hObject,eventdata)untitled('checkbox1_Callback',hObject,eventdata,guidata(hObject)) Error while evaluating UIControl Callback

Thanks for any help.

答:
Your current function will:

Create a set of axis and plot data. This plot is accessible with the handle distanceX_Plotted.

Attempt to delete distanceX_Plotted, which does not exist since it didn't enter the first part of the if-else block.

If you want to plot something on the axis handle.axis2 or delete it, you need to plot in the wanted axis, or delete the axis (and not the plot):

```<code>function checkbox1_Callback(hObject, eventdata, handles)
% Hint: get(hObject,'Value') returns toggle state of checkbox1
if get(hObject, 'Value') == 1
    x = handles.x;
    distanceX_Plot = evalin('base', 'CAN2_MPC_C19_Dist_X_VehObj0_Cval_MPC');
    hold on;
    distanceX_Plotted = plot(x,distanceX_Plot, 'r','Parent', handles.axes2); % modified
    legend('Distance X')
    hold off;
else
    delete(handles.axes2); % modified
end
</code>```

EDIT: If you would like to remove the last line you have plotted, write this in else block:

```<code>if ~isempty(handles.axes2.Children)
    delete(handles.axes2.Children(end));
end
</code>```

It will remove the last line you printed on axes2.

Body:
everyone. Probably, I am making a utterly silly mistake here but here is the problem:

I have made a GUI using MATLAB GUIDE. I added some checkboxes to the GUI so that they will plot something on axes2 if checked and delete it otherwise. In case if you ask, there are going to be other plots so there is hold on and off. It works like this:

function checkbox1_Callback(hObject, eventdata, handles)
% Hint: get(hObject,'Value') returns toggle state of checkbox1
if get(hObject, 'Value') == 1
    axes(handles.axes2);
    x = handles.x;
    distanceX_Plot = evalin('base', 'CAN2_MPC_C19_Dist_X_VehObj0_Cval_MPC');
    hold on;
    distanceX_Plotted = plot(x,distanceX_Plot, 'r');
    legend('Distance X')
    hold off;
else
    delete(distanceX_Plotted);
end

but the distanceX_Plotted in the IF part gets underlined and says variable might be unused and the second distanceX_Plotted in the ELSE statement says that variable may be used before it is defined.

The complete error is like this:

Undefined function or variable 'distanceX_Plotted'.

Error in untitled>checkbox1_Callback (line 224) delete(distanceX_Plotted);

Error in gui_mainfcn (line 95) feval(varargin{:});

Error in untitled (line 42) gui_mainfcn(gui_State, varargin{:});

Error in matlab.graphics.internal.figfile.FigFile/read>@(hObject,eventdata)untitled('checkbox1_Callback',hObject,eventdata,guidata(hObject)) Error while evaluating UIControl Callback

Thanks for any help.

Body:
Your current function will:

Create a set of axis and plot data. This plot is accessible with the handle distanceX_Plotted.

Attempt to delete distanceX_Plotted, which does not exist since it didn't enter the first part of the if-else block.

If you want to plot something on the axis handle.axis2 or delete it, you need to plot in the wanted axis, or delete the axis (and not the plot):

function checkbox1_Callback(hObject, eventdata, handles)
% Hint: get(hObject,'Value') returns toggle state of checkbox1
if get(hObject, 'Value') == 1
    x = handles.x;
    distanceX_Plot = evalin('base', 'CAN2_MPC_C19_Dist_X_VehObj0_Cval_MPC');
    hold on;
    distanceX_Plotted = plot(x,distanceX_Plot, 'r','Parent', handles.axes2); % modified
    legend('Distance X')
    hold off;
else
    delete(handles.axes2); % modified
end

EDIT: If you would like to remove the last line you have plotted, write this in else block:

if ~isempty(handles.axes2.Children)
    delete(handles.axes2.Children(end));
end

It will remove the last line you printed on axes2.


问:
Go ahead only if (condition)
I have this code

```<code>spinRoullete.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (errors()){
             something
               return;}
            if (!errors()){
               something else}
</code>```

And this is for errors

```<code> private boolean errors() {
    if (Rone.isChecked()) {
        if (nr1.getText().length() == 0) {
            nr1.setError("");
        } else {
            nr1.setError(null);
        }
    }           if (Rtwo.isChecked()) {
        if (nr1.getText().length() == 0) {
            nr1.setError("");
        } else {
            nr1.setError(null);
        }
        if (nr2.getText().length() == 0) {
            nr2.setError("");
        } else {
            nr2.setError(null);
        }
    }
</code>```

Something here it's wrong and I don't know what .. The texterrors appears, and disappear when I complete the nr1, or nr2 (edittexts) but something it's wrong with the second if from onClick. When the errors disappear I want to go forward to that second if ( that with something else).. What should I edit to do this?

答:
First off, minor optimization improvement: You have this code (formatted for improved readability, same code):

```<code>if (errors()){
     something...
     return;
}
if (!errors()){
   something else...
}
</code>```

But you don't need that least one since you have a return statement:

```<code>if(errors()){
    something
    return;
}

something else...
</code>```

The method is called once instead of twice if there isn't an error, so you avoid problems there.

But you never return any visible value from errors(). Most likely, you have return true at the bottom, meaning it always goes into the first if statement. Simply change the method:

```<code>private boolean errors() {
    boolean i1 = false;//if no errors, return false
    if (Rone.isChecked()) {
        if (nr1.getText().length() == 0) {
            nr1.setError("");
            i1 = true;//There is at least one error
        } else {
            nr1.setError(null);
        }
    }
    if (Rtwo.isChecked()) {
        if (nr1.getText().length() == 0) {
            nr1.setError("");
            i1 = true;//there is at least one error
        } else {
            nr1.setError(null);
        }
        if (nr2.getText().length() == 0) {
            nr2.setError("");
            return true;//This is the last thing that can happen, so just return true. There is at least one error, this one
        } else {
            nr2.setError(null);
            return i1;//there could have been an error earlier, so return i1
        }
    }
    return i1;//and if the last box isn't checked, return i1 here
}
</code>```

Most likely, you have return true at the bottom of the method. That means it will always go into the first if-statement and return even if there are no errors.

And you should really start looking into indentation conventions, some of the code you posted is very hard to read because of that

Title: Go ahead only if (condition)

Body:
I have this code

spinRoullete.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (errors()){
             something
               return;}
            if (!errors()){
               something else}

And this is for errors

 private boolean errors() {
    if (Rone.isChecked()) {
        if (nr1.getText().length() == 0) {
            nr1.setError("");
        } else {
            nr1.setError(null);
        }
    }           if (Rtwo.isChecked()) {
        if (nr1.getText().length() == 0) {
            nr1.setError("");
        } else {
            nr1.setError(null);
        }
        if (nr2.getText().length() == 0) {
            nr2.setError("");
        } else {
            nr2.setError(null);
        }
    }

Something here it's wrong and I don't know what .. The texterrors appears, and disappear when I complete the nr1, or nr2 (edittexts) but something it's wrong with the second if from onClick. When the errors disappear I want to go forward to that second if ( that with something else).. What should I edit to do this?

Body:
First off, minor optimization improvement: You have this code (formatted for improved readability, same code):

if (errors()){
     something...
     return;
}
if (!errors()){
   something else...
}

But you don't need that least one since you have a return statement:

if(errors()){
    something
    return;
}

something else...

The method is called once instead of twice if there isn't an error, so you avoid problems there.

But you never return any visible value from errors(). Most likely, you have return true at the bottom, meaning it always goes into the first if statement. Simply change the method:

private boolean errors() {
    boolean i1 = false;//if no errors, return false
    if (Rone.isChecked()) {
        if (nr1.getText().length() == 0) {
            nr1.setError("");
            i1 = true;//There is at least one error
        } else {
            nr1.setError(null);
        }
    }
    if (Rtwo.isChecked()) {
        if (nr1.getText().length() == 0) {
            nr1.setError("");
            i1 = true;//there is at least one error
        } else {
            nr1.setError(null);
        }
        if (nr2.getText().length() == 0) {
            nr2.setError("");
            return true;//This is the last thing that can happen, so just return true. There is at least one error, this one
        } else {
            nr2.setError(null);
            return i1;//there could have been an error earlier, so return i1
        }
    }
    return i1;//and if the last box isn't checked, return i1 here
}

Most likely, you have return true at the bottom of the method. That means it will always go into the first if-statement and return even if there are no errors.

And you should really start looking into indentation conventions, some of the code you posted is very hard to read because of that


问:
Error : Trying to get property of non-object
I have table Authors and table Uploads and I am simply trying to get all uploads for a certain author by author_id in the Uploads table.

For that purpose I have a method in my controller looking like this :

```<code>public function author_works()
    {

        $uploads= Upload::where('author_id', 3)->first();

        return view('author-works')->with('uploads',$uploads);
    }
</code>```

My view is :

```<code>  @extends('layouts.app')
@section('content')
    <h1>Uploads</h1>
    @if(count($uploads)>0)
        @foreach($uploads as $upload)
            <div class="well">
                <h3><a href="/uploads/{{$upload->id}}">{{$upload->name}}</a> </h3>
                <small>Written on {{$upload->created_at}}</small>

            </div>
        @endforeach
      {{--  {{$uploads->links()}}--}}
    @else
        <p>No uploads found</p>
    @endif

@endsection
</code>```

When I debug with dd($uploads); in the controller I am seeing the following, which is actually the right record :

```<code> #attributes: array:9 [▼
    "id" => 7
    "name" => "Fsdf"
    "description" => "fsdfsdffds"
    "created_at" => "2017-12-07 21:29:53"
    "updated_at" => "2017-12-07 21:29:53"
    "user_id" => 1
    "avtor_id" => 3
  ]
  #original: array:9 [▼
    "id" => 7
    "name" => "Fsdf"
    "description" => "fsdfsdffds"
    "created_at" => "2017-12-07 21:29:53"
    "updated_at" => "2017-12-07 21:29:53"
    "user_id" => 1
    "avtor_id" => 3
  ]
</code>```

Can someone explain why am I getting the error?

答:
When you're using first() method, you're getting an object instead of collection. Use get():

```<code>$uploads = Upload::where('author_id', 3)->get();
</code>```

Body:
I have table Authors and table Uploads and I am simply trying to get all uploads for a certain author by author_id in the Uploads table.

For that purpose I have a method in my controller looking like this :

public function author_works()
    {

        $uploads= Upload::where('author_id', 3)->first();

        return view('author-works')->with('uploads',$uploads);
    }

My view is :

  @extends('layouts.app')
@section('content')

Uploads

    @if(count($uploads)>0)
        @foreach($uploads as $upload)

id}}">{{$upload->name}}

                Written on {{$upload->created_at}}

        @endforeach
      {{--  {{$uploads->links()}}--}}
    @else

No uploads found

    @endif

@endsection

When I debug with dd($uploads); in the controller I am seeing the following, which is actually the right record :

 #attributes: array:9 [▼
    "id" => 7
    "name" => "Fsdf"
    "description" => "fsdfsdffds"
    "created_at" => "2017-12-07 21:29:53"
    "updated_at" => "2017-12-07 21:29:53"
    "user_id" => 1
    "avtor_id" => 3
  ]
  #original: array:9 [▼
    "id" => 7
    "name" => "Fsdf"
    "description" => "fsdfsdffds"
    "created_at" => "2017-12-07 21:29:53"
    "updated_at" => "2017-12-07 21:29:53"
    "user_id" => 1
    "avtor_id" => 3
  ]

Can someone explain why am I getting the error?

Body:
When you're using first() method, you're getting an object instead of collection. Use get():

$uploads = Upload::where('author_id', 3)->get();


问:
How is VXLAN related to SDN?
I am currently setting up a testing SDN environment, so I am familiar with the sdn concept (separating the Control Plane from the Data Plane of a Switch).
Within my research I was often reading about VXLAN when there was talking of SDN.
Now I am a bit confused, because I understand VXLAN as a Tunneling Protocol and I dont know how this would be related to my idea of SDN.

Another question I would like to ask is: Would it be possible to Connect a Switch over several non-sdn Networks to a existing SDN Topology/ SDN Controller with the VXLAN Technology?

Thank you in advance

答:
you should differenciate between SDN as a concept and VXLAN as a tunneling protocol.

The later used to tag packets and hence you can do some kind of seperation in layer-2. This technique helps with network slicing and have been used in flowvisor.

Forwarding traffic through non SDN network have been studied in many works. I suggest you to read the last one

Magneto: Unified Fine-grained Path Control in Legacy and OpenFlow Hybrid Networks

Good luck

Title: How is VXLAN related to SDN?


问:
how can i make a threadsafe progress bar in C#? what am i doing wrong?
Hey everyone, can someone let me know what they see wrong with this code ?

it throws "Cross-thread operation not valid" exception, on

```<code>_DialogueThread.Start();
</code>```

but if i remove "owner" from

```<code>_progressDialogue = new Progresser{Owner = _owner, StartPosition = FormStartPosition.CenterParent};
</code>```

the exception wont be thrown but the progressDialouge will be shown then hidden right away .

now i understand why this the error is thrown if i set the progressDialouge.Owner to a parent form that was created on a different thread. but why dose the form disappears when i dont ?  what am i doing wrong ?

thanks

```<code>class Sampleer : BackgroundWorker
{
    private Progresser _progressDialogue;
    private Thread _DialogueThread;
    private Form _owner;
    private bool _SampleSuccess;

    public Sampleer(Form owner)
    {
        _owner = owner;
        _progressDialogue = new Progresser{Owner = _owner, StartPosition = FormStartPosition.CenterParent};
        _progressDialogue.Closed += ProgressDialogueClosed;
        WorkerReportsProgress = true;
        WorkerSupportsCancellation = true;
        DoWork += Sampleer_DoWork;
        RunWorkerCompleted += Sampleer_RunWorkerCompleted;
        ProgressChanged += Sampleer_ProgressChanged;
    }

    private void Sampleer_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {

       //UPDATE STATUS CODE IS HERE

    }

    void ProgressDialogueClosed(object sender, EventArgs e)
    {
        CancelAsync();
        Dispose();
    }

    void Sampleer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //FINISH PROCESS
    }

    void Sampleer_DoWork(object sender, DoWorkEventArgs e)
    {

        _DialogueThread = new Thread(_progressDialogue.Show);
        _DialogueThread.Start();

        //DO LONG PROCESS HERE
    }
}
</code>```

答:
There are a few mistakes in your approach. Let me point them out one by one.

You inherit BackgroundWorker. That is fine. But you create another thread inside (_DialogueThread). There is no need. DoWork() method runs in a separate thread.

You create/use/manipulate a UI element in another thread. Now, always remember. A Thread never creates a UI element. Its the other way around. A UI element creates a Thread. Progresser in your case should be creating a new Thread or using BackgroundWorker to do any background work you require.

`

Body:
Hey everyone, can someone let me know what they see wrong with this code ?

it throws "Cross-thread operation not valid" exception, on

_DialogueThread.Start();

but if i remove "owner" from

_progressDialogue = new Progresser{Owner = _owner, StartPosition = FormStartPosition.CenterParent};

the exception wont be thrown but the progressDialouge will be shown then hidden right away .

now i understand why this the error is thrown if i set the progressDialouge.Owner to a parent form that was created on a different thread. but why dose the form disappears when i dont ?  what am i doing wrong ?

thanks

class Sampleer : BackgroundWorker
{
    private Progresser _progressDialogue;
    private Thread _DialogueThread;
    private Form _owner;
    private bool _SampleSuccess;

    public Sampleer(Form owner)
    {
        _owner = owner;
        _progressDialogue = new Progresser{Owner = _owner, StartPosition = FormStartPosition.CenterParent};
        _progressDialogue.Closed += ProgressDialogueClosed;
        WorkerReportsProgress = true;
        WorkerSupportsCancellation = true;
        DoWork += Sampleer_DoWork;
        RunWorkerCompleted += Sampleer_RunWorkerCompleted;
        ProgressChanged += Sampleer_ProgressChanged;
    }

    private void Sampleer_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {

       //UPDATE STATUS CODE IS HERE

    }

    void ProgressDialogueClosed(object sender, EventArgs e)
    {
        CancelAsync();
        Dispose();
    }

    void Sampleer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        //FINISH PROCESS
    }

    void Sampleer_DoWork(object sender, DoWorkEventArgs e)
    {

        _DialogueThread = new Thread(_progressDialogue.Show);
        _DialogueThread.Start();

        //DO LONG PROCESS HERE
    }
}


问:
How to properly show progress of async tasks used by Google Room
I'm using Google Room to implement persistence of data in my Android app (Kotlin code). Room demands all the operations (queries to and from the database) to be async. I would like the user to wait for the operation to execute, preventing him from interacting with components that would not be configured properly before the end of the query. How can I achieve this, since I can't access the UI thread from a async task?

PS: I also do some calls to an API where the progress/loading indicator would be nice to have. I'm using RxJava in those calls, but I'm fairly new to this technology, and I'm not sure how to properly structure it.

Sample of a db operation:

```<code>private fun getDataFromCache() {
  //show progress indicator here
        execute({
            try {
                //Get items from cache
                val entities = daoData.findAll()

                if (entities.isNotEmpty()) {
                    //do something
                } else {
                    //do something else
                }
            }
            catch (e: Exception){
                Log.e("error", e.toString())
            }
            finally{
                //dismiss progress indicator here
            }
        })
    }
</code>```

答:
To prevent the user from using the app while the fetch is working you can use a library like KProgressHUD to display a modal, user interface blocking HUD, which can optionally include a progress indicator. You only need to replace the show progress indicator here comment with the modal HUD creation and //dismiss progress indicator here with removal of the HUD on the UI thread.

With regards to progress, you have to manually update the HUD progress inside your execute code. First you need to split your dao findAll() call into one that returns the number of elements you have in total (some SELECT COUNT(*) query) to know how long the total progress bar might be. Then, instead of findAll() you would need to create batched/paged calls to the database, fetching N records in a loop. Inside this loop you can then update the HUD with the percentage of your current loop progress vs the total count you got before starting.

I'm not familiar with the Room API, so I can't provide any pseudo code on such a loop, but usually it all boils down to opening an SQL cursor and keep fetching batches of data in a loop until it is exhausted, keeping track of how many have items have you read and accumulating them in a list.

Body:
I'm using Google Room to implement persistence of data in my Android app (Kotlin code). Room demands all the operations (queries to and from the database) to be async. I would like the user to wait for the operation to execute, preventing him from interacting with components that would not be configured properly before the end of the query. How can I achieve this, since I can't access the UI thread from a async task?

PS: I also do some calls to an API where the progress/loading indicator would be nice to have. I'm using RxJava in those calls, but I'm fairly new to this technology, and I'm not sure how to properly structure it.

Sample of a db operation:

private fun getDataFromCache() {
  //show progress indicator here
        execute({
            try {
                //Get items from cache
                val entities = daoData.findAll()

                if (entities.isNotEmpty()) {
                    //do something
                } else {
                    //do something else
                }
            }
            catch (e: Exception){
                Log.e("error", e.toString())
            }
            finally{
                //dismiss progress indicator here
            }
        })
    }


问:
Plot start-end time slots - matplotlib python
I'm trying to plot time slots. I have two ndarrays of 'start' and 'end' points.
I want to draw it as chunks on a figure. Keep in mind that the chunks are not consecutive and there are gaps between the slots.

Until now I have tried to use patches:

```<code>for x_1 , x_2 in zip(s_data['begin'].values ,s_data['end'].values):
ax1.add_patch(Rectangle((x_1,0),x_2-x_1,0.5))
plt.show()
</code>```

But its only giving me hald blue figure.

While I want something like this

答:
The approach is correct. You just need to scale the axes such that the complete plot is within its range.

```<code>import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({"begin": [1,4,6,9], "end" : [3,5,8,12]})

fig, ax = plt.subplots()

for x_1 , x_2 in zip(df['begin'].values ,df['end'].values):
    ax.add_patch(plt.Rectangle((x_1,0),x_2-x_1,0.5))

ax.autoscale()
ax.set_ylim(-2,2)
plt.show()
</code>```

It is worth noting that matplotlib has a function broken_barh, which simplifies the creation of such charts.

```<code>import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({"begin": [1,4,6,9], "end" : [3,5,8,12]})

fig, ax = plt.subplots()

ax.broken_barh(list(zip(df["begin"].values, (df["end"] - df["begin"]).values)), (0, 0.5))

ax.set_ylim(-2,2)
plt.show()
</code>```

Giving the same diagram as the above.

ContentLicense: CC BY-SA 4.0

Body:
I'm trying to plot time slots. I have two ndarrays of 'start' and 'end' points.
I want to draw it as chunks on a figure. Keep in mind that the chunks are not consecutive and there are gaps between the slots.

Until now I have tried to use patches:

for x_1 , x_2 in zip(s_data['begin'].values ,s_data['end'].values):
ax1.add_patch(Rectangle((x_1,0),x_2-x_1,0.5))
plt.show()

But its only giving me hald blue figure.

While I want something like this

Body:
The approach is correct. You just need to scale the axes such that the complete plot is within its range.

import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({"begin": [1,4,6,9], "end" : [3,5,8,12]})

fig, ax = plt.subplots()

for x_1 , x_2 in zip(df['begin'].values ,df['end'].values):
    ax.add_patch(plt.Rectangle((x_1,0),x_2-x_1,0.5))

ax.autoscale()
ax.set_ylim(-2,2)
plt.show()

It is worth noting that matplotlib has a function broken_barh, which simplifies the creation of such charts.

import matplotlib.pyplot as plt
import pandas as pd

df = pd.DataFrame({"begin": [1,4,6,9], "end" : [3,5,8,12]})

fig, ax = plt.subplots()

ax.broken_barh(list(zip(df["begin"].values, (df["end"] - df["begin"]).values)), (0, 0.5))

ax.set_ylim(-2,2)
plt.show()

Giving the same diagram as the above.


问:
Globalize accessors on subset of available locales
By design, some classes will deal with only a subset of available languages.

the globalize-accessors gem is quite useful, however, the rendering requires that the following be defined

```<code>Class.globalize_attribute_names
</code>```

so while available_locales = [:en, :ru, :fr, :de], the goal is to work with a smaller array [:en, :ru]

The documentation states Calling globalize_accessors with no options will therefore generate accessor methods for all translated fields and available languages.  But the purported way to invoke is in the model

```<code>globalize_accessors :locales => [:en, :fr], :attributes => [:title]
</code>```

How can the globalize_accessorsmethod refer to an array, something generated by the likes of

```<code>@post.owner.ownerlocales.pluck('locale')
</code>```

(although the array values are quoted...)

答:
A working solution found but that does not address the above question, is based on the fact that globalize-accessors

gives you access to methods: title_pl, title_en, title_pl=, title_en=

Thus, a controller method that generates a whitelist

```<code>@locales =  []
@post.owner.ownerlocales.each do |ol|
  locale = ol.locale
  @locales.push(locale)
end
</code>```

... then process in the view filtering out the globalize_processors from whitelist

```<code><% Post.globalize_attribute_names.each do |lang| %>
  <% my_string = lang.to_s %>
  <% @locales.each do |locale| %>
    <% checkstring = "_" + locale %>
    <% if my_string.include? checkstring %>
      <div class="row">
        <%= t(lang[0..-4]) %>   -   <%= lang[-2, 2] %> <br />
        <%= f.text_area lang, rows: "3" %>
      </div>
    <% end %>
  <% end %>
<% end %>
</code>```

Not efficient, functional.

Body:
By design, some classes will deal with only a subset of available languages.

the globalize-accessors gem is quite useful, however, the rendering requires that the following be defined

Class.globalize_attribute_names

so while available_locales = [:en, :ru, :fr, :de], the goal is to work with a smaller array [:en, :ru]

The documentation states Calling globalize_accessors with no options will therefore generate accessor methods for all translated fields and available languages.  But the purported way to invoke is in the model

globalize_accessors :locales => [:en, :fr], :attributes => [:title]

How can the globalize_accessorsmethod refer to an array, something generated by the likes of

@post.owner.ownerlocales.pluck('locale')

(although the array values are quoted...)

Body:
A working solution found but that does not address the above question, is based on the fact that globalize-accessors

gives you access to methods: title_pl, title_en, title_pl=, title_en=

Thus, a controller method that generates a whitelist

@locales =  []
@post.owner.ownerlocales.each do |ol|
  locale = ol.locale
  @locales.push(locale)
end

... then process in the view filtering out the globalize_processors from whitelist

<% Post.globalize_attribute_names.each do |lang| %>
  <% my_string = lang.to_s %>
  <% @locales.each do |locale| %>
    <% checkstring = "_" + locale %>
    <% if my_string.include? checkstring %>
      <div class="row">
        <%= t(lang[0..-4]) %> &nbsp;&nbsp;-&nbsp;&nbsp; <%= lang[-2, 2] %> <br />
        <%= f.text_area lang, rows: "3" %>
      </div>
    <% end %>
  <% end %>
<% end %>

Not efficient, functional.


问:
How would I go about creating a file compressor similar to ZIP archives in a language like C/C++?
So I was thinking of how a .zip archive is structured and then I thought, how could I create my own archive format.</p>

答: Download the sources of bzip2 and compile them. And then go from there.</p>


问:
App Stop Working without error and mixing versions issue
When I'm clicking on share icon then application stopped and it doesn't show any error in logcat, only five lines which doesn't seems like an error to me. Also, there are 5 fragment, when I open fragment 4 after opening app, it stopped but when I go to fragment 2 then 3 then 5, it doesn't stop. Even my minSdkVersion 15 and targetSdkVersion 18, my app is not running, it's stopped in most devices.

There's a warning shows in gradle (Module:App) on appcompat

```<code>all com.android.support libraries must use the exact same version found versions 26.1.0, 25.2.0
</code>```

This is my gradle

```<code>apply plugin: 'com.android.application'
apply plugin: 'realm-android'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.2"
    defaultConfig {
        applicationId "com.balrajarpit.balrajarpit"
        minSdkVersion 15
        targetSdkVersion 18
        versionCode 2
        versionName "1.1"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
        multiDexEnabled = true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        dexOptions {
            javaMaxHeapSize "4g"
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

    compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support:design:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.android.support:recyclerview-v7:26.+'
    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'com.android.support:cardview-v7:26.+'
    compile 'com.android.support:support-vector-drawable:26.+'
    compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
    compile 'com.android.support:support-v4:26.+'
    compile 'com.squareup.picasso:picasso:2.5.2'
    compile 'com.mcxiaoke.volley:library:1.0.19'
    compile 'com.google.code.gson:gson:2.2.4'
    compile 'com.google.android.gms:play-services:11.+'

    compile('com.squareup.retrofit2:retrofit:2.0.0-beta4') {
        exclude module: 'okhttp'
    }
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.picasso:picasso:2.5.2'

    // ripple effect library
    compile 'com.balysv:material-ripple:1.0.2'
    testCompile 'junit:junit:4.12'
}
apply plugin: 'com.google.gms.google-services'
</code>```

Activity

```<code>import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.balysv.materialripple.MaterialRippleLayout;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.balrajarpit.balrajarpit.adapter.AdapterComments;
import com.balrajarpit.balrajarpit.connection.API;
import com.balrajarpit.balrajarpit.connection.RestAdapter;
import com.balrajarpit.balrajarpit.connection.callbacks.CallbackDetailsPost;
import com.balrajarpit.balrajarpit.data.AppConfig;
import com.balrajarpit.balrajarpit.data.Constant;
import com.balrajarpit.balrajarpit.data.SharedPref;
import com.balrajarpit.balrajarpit.model.Comment;
import com.balrajarpit.balrajarpit.model.Post;
import com.balrajarpit.balrajarpit.realm.RealmController;
import com.balrajarpit.balrajarpit.utils.NetworkCheck;
import com.balrajarpit.balrajarpit.utils.Tools;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class ActivityPostDetails extends AppCompatActivity {

    public static final String EXTRA_OBJC = "key.EXTRA_OBJC";
    public static final String EXTRA_NOTIF = "key.EXTRA_NOTIF";

    // give preparation animation activity transition
    public static void navigate(AppCompatActivity activity, View transitionView, Post obj) {
        Intent intent = new Intent(activity, ActivityPostDetails.class);
        intent.putExtra(EXTRA_OBJC, obj);
        ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, transitionView, EXTRA_OBJC);
        ActivityCompat.startActivity(activity, intent, options.toBundle());
    }

    private Toolbar toolbar;
    private ActionBar actionBar;
    private View parent_view;
    private MenuItem read_later_menu;
    private SwipeRefreshLayout swipe_refresh;

    // extra obj
    private Post post;
    private boolean from_notif;

    private SharedPref sharedPref;
    private boolean flag_read_later;
    private Call<CallbackDetailsPost> callbackCall = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_post_details);
        parent_view = findViewById(android.R.id.content);
        swipe_refresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
        sharedPref = new SharedPref(this);

        // animation transition
        ViewCompat.setTransitionName(findViewById(R.id.image), EXTRA_OBJC);

        // get extra object
        post = (Post) getIntent().getSerializableExtra(EXTRA_OBJC);
        from_notif = getIntent().getBooleanExtra(EXTRA_NOTIF, false);
        initToolbar();

        displayPostData(true);
        prepareAds();

        if (post.isDraft()) requestAction();

        // on swipe
        swipe_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                requestAction();
            }
        });

        // get enabled controllers
        Tools.requestInfoApi(this);

        // analytics tracking
        ThisApplication.getInstance().trackScreenView("View post : "+post.title_plain);

    }

    private void initToolbar() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
        actionBar.setTitle("");
    }

    private void requestDetailsPostApi() {
        API api = RestAdapter.createAPI();
        callbackCall = api.getPostDetialsById(post.id);
        callbackCall.enqueue(new Callback<CallbackDetailsPost>() {
            @Override
            public void onResponse(Call<CallbackDetailsPost> call, Response<CallbackDetailsPost> response) {
                CallbackDetailsPost resp = response.body();
                if (resp != null && resp.status.equals("ok")) {
                    post = resp.post;
                    displayPostData(false);
                    swipeProgress(false);
                } else {
                    onFailRequest();
                }
            }

            @Override
            public void onFailure(Call<CallbackDetailsPost> call, Throwable t) {
                if (!call.isCanceled()) onFailRequest();
            }

        });
    }

    private void requestAction() {
        showFailedView(false, "");
        swipeProgress(true);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                requestDetailsPostApi();
            }
        }, Constant.DELAY_TIME_MEDIUM);
    }

    private void onFailRequest() {
        swipeProgress(false);
        if (NetworkCheck.isConnect(this)) {
            showFailedView(true, getString(R.string.failed_text));
        } else {
            showFailedView(true, getString(R.string.no_internet_text));
        }
    }

    private void displayPostData(boolean is_draft) {
        ((TextView) findViewById(R.id.title)).setText(Html.fromHtml(post.title));

        WebView webview = (WebView) findViewById(R.id.content);
        String html_data = "<style>img{max-width:100%;height:auto;} iframe{width:100%;}</style> ";
        html_data += post.content;
        webview.getSettings().setJavaScriptEnabled(true);
        webview.getSettings();
        webview.getSettings().setBuiltInZoomControls(true);
        webview.setBackgroundColor(Color.TRANSPARENT);
        webview.setWebChromeClient(new WebChromeClient());
        webview.loadData(html_data, "text/html; charset=UTF-8", null);
        // disable scroll on touch
        webview.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return (event.getAction() == MotionEvent.ACTION_MOVE);
            }
        });

        ((TextView) findViewById(R.id.date)).setText(Tools.getFormatedDate(post.date));
        ((TextView) findViewById(R.id.comment)).setText(post.comment_count + "");
        ((TextView) findViewById(R.id.tv_comment)).setText(getString(R.string.show_tv_comments) + " (" + post.comment_count + ")");
        ((TextView) findViewById(R.id.category)).setText(Html.fromHtml(Tools.getCategoryTxt(post.categories)));
        Tools.displayImageThumbnail(this, post, ((ImageView) findViewById(R.id.image)));

        if(is_draft){
           return;
        }
        // when show comments click
        ((MaterialRippleLayout) findViewById(R.id.bt_show_comment)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (post.comments.size() <= 0) {
                    Snackbar.make(parent_view, R.string.post_have_no_comment, Snackbar.LENGTH_SHORT).show();
                    return;
                }
                dialogShowComments(post.comments);
            }
        });

        // when post comments click
        ((MaterialRippleLayout) findViewById(R.id.bt_send_comment)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!AppConfig.MUST_REGISTER_TO_COMMENT) {
                    Intent i = new Intent(ActivityPostDetails.this, ActivityWebView.class);
                    if (sharedPref.isRespondEnabled()) {
                        i = new Intent(ActivityPostDetails.this, ActivitySendComment.class);
                    }
                    i.putExtra(EXTRA_OBJC, post);
                    startActivity(i);
                } else {
                    Tools.dialogCommentNeedLogin(ActivityPostDetails.this, post.url);
                }
            }
        });
        Snackbar.make(parent_view, R.string.post_detail_displayed_msg, Snackbar.LENGTH_SHORT).show();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int item_id = item.getItemId();
        if (item_id == android.R.id.home) {
            onBackPressed();
        } else if (item_id == R.id.action_share) {
            Tools.methodShare(ActivityPostDetails.this, post);
        } else if (item_id == R.id.action_later) {
            if (post.isDraft()) {
                Snackbar.make(parent_view, R.string.cannot_add_to_read_later, Snackbar.LENGTH_SHORT).show();
                return true;
            }
            String str;
            if (flag_read_later) {
                RealmController.with(this).deletePost(post.id);
                str = getString(R.string.remove_from_msg);
            } else {
                RealmController.with(this).savePost(post);
                str = getString(R.string.added_to_msg);
            }
            Snackbar.make(parent_view, "Post " + str + " Read Later", Snackbar.LENGTH_SHORT).show();
            refreshReadLaterMenu();
        } else if (item_id == R.id.action_browser) {
            Tools.directLinkToBrowser(this, post.url);
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        getMenuInflater().inflate(R.menu.menu_activity_post_details, menu);
        read_later_menu = menu.findItem(R.id.action_later);
        refreshReadLaterMenu();
        return true;
    }

    private void dialogShowComments(List<Comment> items) {

        final Dialog dialog = new Dialog(ActivityPostDetails.this);
        dialog.setCancelable(true);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // before
        dialog.setContentView(R.layout.dialog_comments);

        WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
        lp.copyFrom(dialog.getWindow().getAttributes());
        lp.width = WindowManager.LayoutParams.MATCH_PARENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;

        RecyclerView recyclerView = (RecyclerView) dialog.findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);
        AdapterComments mAdapter = new AdapterComments(this, items);
        recyclerView.setAdapter(mAdapter);

        ((ImageView) dialog.findViewById(R.id.img_close)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                dialog.dismiss();
            }
        });

        dialog.show();
        dialog.getWindow().setAttributes(lp);
    }

    private void refreshReadLaterMenu() {
        flag_read_later = RealmController.with(this).getPost(post.id) != null;
        Drawable drawable = read_later_menu.getIcon();
        if (flag_read_later) {
            drawable.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_ATOP);
        } else {
            drawable.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
        }
    }

    private void prepareAds() {
        if (AppConfig.ENABLE_ADSENSE && NetworkCheck.isConnect(getApplicationContext())) {
            AdView mAdView = (AdView) findViewById(R.id.ad_view);
            AdRequest adRequest = new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR).build();
            // Start loading the ad in the background.
            mAdView.loadAd(adRequest);
        } else {
            ((RelativeLayout) findViewById(R.id.banner_layout)).setVisibility(View.GONE);
        }
    }

    private void showFailedView(boolean show, String message) {
        View lyt_failed = (View) findViewById(R.id.lyt_failed);
        View lyt_main_content = (View) findViewById(R.id.lyt_main_content);

        ((TextView) findViewById(R.id.failed_message)).setText(message);
        if (show) {
            lyt_main_content.setVisibility(View.GONE);
            lyt_failed.setVisibility(View.VISIBLE);
        } else {
            lyt_main_content.setVisibility(View.VISIBLE);
            lyt_failed.setVisibility(View.GONE);
        }
        ((Button) findViewById(R.id.failed_retry)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                requestAction();
            }
        });
    }

    private void swipeProgress(final boolean show) {
        if (!show) {
            swipe_refresh.setRefreshing(show);
            return;
        }
        swipe_refresh.post(new Runnable() {
            @Override
            public void run() {
                swipe_refresh.setRefreshing(show);
            }
        });
    }

    @Override
    public void onBackPressed() {
        if(from_notif) {
            startActivity(new Intent(getApplicationContext(), ActivityMain.class));
            finish();
        } else {
            super.onBackPressed();
        }
    }
}
</code>```

Logcat

```<code>12-09 13:56:43.962 6867-6914/com.balrajarpit.balrajarpit D/FA: Logging event (FE): app_exception(_ae), Bundle[{firebase_event_origin(_o)=crash, firebase_screen_class(_sc)=ActivityPostDetails, firebase_screen_id(_si)=8020478545849927104, timestamp=1512808003957, fatal=1}]
12-09 13:56:43.979 6867-6914/com.balrajarpit.balrajarpit V/FA: Connecting to remote service
12-09 13:56:43.985 6867-6914/com.balrajarpit.balrajarpit V/FA: Recording user engagement, ms: 23008
12-09 13:56:43.991 6867-6914/com.balrajarpit.balrajarpit D/FA: Logging event (FE): user_engagement(_e), Bundle[{firebase_event_origin(_o)=auto, engagement_time_msec(_et)=23008, firebase_screen_class(_sc)=ActivityPostDetails, firebase_screen_id(_si)=8020478545849927104}]
12-09 13:56:44.012 6867-6914/com.balrajarpit.balrajarpit V/FA: Connection attempt already in progress
</code>```

答:
I am not sure if it is the problem in this case, but using different versions of support libraries can cause runtime crashes. You can find the ones that use a different version (maybe used internally by another library) by executing the following command in (android studio) terminal:

```<code>gradlew -q dependencies app:dependencies --configuration compile
</code>```

If the command doesn't work, you maybe have to configure a gradle wrapper first. To do so, add the following to your project build.gradle file:

```<code>task wrapper(type: Wrapper) {
    gradleVersion = '4.1'
}
</code>```

and execute the command

```<code>gradle wrapper
</code>```

from terminal. If it still doesn't work, gradle might not be in your PATH, you can find it in the Android Studio installation folder if you want to add it.

Once you know which one uses a different version, just add it as a dependency yourself with the correct version to override the other version and sync.

It worked for me this way when I had the problem, hope it helps!

Body:
When I'm clicking on share icon then application stopped and it doesn't show any error in logcat, only five lines which doesn't seems like an error to me. Also, there are 5 fragment, when I open fragment 4 after opening app, it stopped but when I go to fragment 2 then 3 then 5, it doesn't stop. Even my minSdkVersion 15 and targetSdkVersion 18, my app is not running, it's stopped in most devices.

There's a warning shows in gradle (Module:App) on appcompat

all com.android.support libraries must use the exact same version found versions 26.1.0, 25.2.0

This is my gradle

apply plugin: 'com.android.application'
apply plugin: 'realm-android'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.2"
    defaultConfig {
        applicationId "com.balrajarpit.balrajarpit"
        minSdkVersion 15
        targetSdkVersion 18
        versionCode 2
        versionName "1.1"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
        multiDexEnabled = true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        dexOptions {
            javaMaxHeapSize "4g"
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

    compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support:design:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.android.support:recyclerview-v7:26.+'
    compile 'com.github.bumptech.glide:glide:3.7.0'
    compile 'com.android.support:cardview-v7:26.+'
    compile 'com.android.support:support-vector-drawable:26.+'
    compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
    compile 'com.android.support:support-v4:26.+'
    compile 'com.squareup.picasso:picasso:2.5.2'
    compile 'com.mcxiaoke.volley:library:1.0.19'
    compile 'com.google.code.gson:gson:2.2.4'
    compile 'com.google.android.gms:play-services:11.+'

    compile('com.squareup.retrofit2:retrofit:2.0.0-beta4') {
        exclude module: 'okhttp'
    }
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.0.1'
    compile 'com.squareup.retrofit2:converter-gson:2.1.0'
    compile 'com.squareup.picasso:picasso:2.5.2'

    // ripple effect library
    compile 'com.balysv:material-ripple:1.0.2'
    testCompile 'junit:junit:4.12'
}
apply plugin: 'com.google.gms.google-services'

Activity

import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.balysv.materialripple.MaterialRippleLayout;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.balrajarpit.balrajarpit.adapter.AdapterComments;
import com.balrajarpit.balrajarpit.connection.API;
import com.balrajarpit.balrajarpit.connection.RestAdapter;
import com.balrajarpit.balrajarpit.connection.callbacks.CallbackDetailsPost;
import com.balrajarpit.balrajarpit.data.AppConfig;
import com.balrajarpit.balrajarpit.data.Constant;
import com.balrajarpit.balrajarpit.data.SharedPref;
import com.balrajarpit.balrajarpit.model.Comment;
import com.balrajarpit.balrajarpit.model.Post;
import com.balrajarpit.balrajarpit.realm.RealmController;
import com.balrajarpit.balrajarpit.utils.NetworkCheck;
import com.balrajarpit.balrajarpit.utils.Tools;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class ActivityPostDetails extends AppCompatActivity {

    public static final String EXTRA_OBJC = "key.EXTRA_OBJC";
    public static final String EXTRA_NOTIF = "key.EXTRA_NOTIF";

    // give preparation animation activity transition
    public static void navigate(AppCompatActivity activity, View transitionView, Post obj) {
        Intent intent = new Intent(activity, ActivityPostDetails.class);
        intent.putExtra(EXTRA_OBJC, obj);
        ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, transitionView, EXTRA_OBJC);
        ActivityCompat.startActivity(activity, intent, options.toBundle());
    }

    private Toolbar toolbar;
    private ActionBar actionBar;
    private View parent_view;
    private MenuItem read_later_menu;
    private SwipeRefreshLayout swipe_refresh;

    // extra obj
    private Post post;
    private boolean from_notif;

    private SharedPref sharedPref;
    private boolean flag_read_later;
    private Call<CallbackDetailsPost> callbackCall = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_post_details);
        parent_view = findViewById(android.R.id.content);
        swipe_refresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
        sharedPref = new SharedPref(this);

        // animation transition
        ViewCompat.setTransitionName(findViewById(R.id.image), EXTRA_OBJC);

        // get extra object
        post = (Post) getIntent().getSerializableExtra(EXTRA_OBJC);
        from_notif = getIntent().getBooleanExtra(EXTRA_NOTIF, false);
        initToolbar();

        displayPostData(true);
        prepareAds();

        if (post.isDraft()) requestAction();

        // on swipe
        swipe_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                requestAction();
            }
        });

        // get enabled controllers
        Tools.requestInfoApi(this);

        // analytics tracking
        ThisApplication.getInstance().trackScreenView("View post : "+post.title_plain);

    }

    private void initToolbar() {
        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
        actionBar.setTitle("");
    }

    private void requestDetailsPostApi() {
        API api = RestAdapter.createAPI();
        callbackCall = api.getPostDetialsById(post.id);
        callbackCall.enqueue(new Callback<CallbackDetailsPost>() {
            @Override
            public void onResponse(Call<CallbackDetailsPost> call, Response<CallbackDetailsPost> response) {
                CallbackDetailsPost resp = response.body();
                if (resp != null && resp.status.equals("ok")) {
                    post = resp.post;
                    displayPostData(false);
                    swipeProgress(false);
                } else {
                    onFailRequest();
                }
            }

            @Override
            public void onFailure(Call<CallbackDetailsPost> call, Throwable t) {
                if (!call.isCanceled()) onFailRequest();
            }

        });
    }

    private void requestAction() {
        showFailedView(false, "");
        swipeProgress(true);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                requestDetailsPostApi();
            }
        }, Constant.DELAY_TIME_MEDIUM);
    }

    private void onFailRequest() {
        swipeProgress(false);
        if (NetworkCheck.isConnect(this)) {
            showFailedView(true, getString(R.string.failed_text));
        } else {
            showFailedView(true, getString(R.string.no_internet_text));
        }
    }

    private void displayPostData(boolean is_draft) {
        ((TextView) findViewById(R.id.title)).setText(Html.fromHtml(post.title));

        WebView webview = (WebView) findViewById(R.id.content);
        String html_data = " ";
        html_data += post.content;
        webview.getSettings().setJavaScriptEnabled(true);
        webview.getSettings();
        webview.getSettings().setBuiltInZoomControls(true);
        webview.setBackgroundColor(Color.TRANSPARENT);
        webview.setWebChromeClient(new WebChromeClient());
        webview.loadData(html_data, "text/html; charset=UTF-8", null);
        // disable scroll on touch
        webview.setOnTouchListener(new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                return (event.getAction() == MotionEvent.ACTION_MOVE);
            }
        });

        ((TextView) findViewById(R.id.date)).setText(Tools.getFormatedDate(post.date));
        ((TextView) findViewById(R.id.comment)).setText(post.comment_count + "");
        ((TextView) findViewById(R.id.tv_comment)).setText(getString(R.string.show_tv_comments) + " (" + post.comment_count + ")");
        ((TextView) findViewById(R.id.category)).setText(Html.fromHtml(Tools.getCategoryTxt(post.categories)));
        Tools.displayImageThumbnail(this, post, ((ImageView) findViewById(R.id.image)));

        if(is_draft){
           return;
        }
        // when show comments click
        ((MaterialRippleLayout) findViewById(R.id.bt_show_comment)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (post.comments.size() <= 0) {
                    Snackbar.make(parent_view, R.string.post_have_no_comment, Snackbar.LENGTH_SHORT).show();
                    return;
                }
                dialogShowComments(post.comments);
            }
        });

        // when post comments click
        ((MaterialRippleLayout) findViewById(R.id.bt_send_comment)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!AppConfig.MUST_REGISTER_TO_COMMENT) {
                    Intent i = new Intent(ActivityPostDetails.this, ActivityWebView.class);
                    if (sharedPref.isRespondEnabled()) {
                        i = new Intent(ActivityPostDetails.this, ActivitySendComment.class);
                    }
                    i.putExtra(EXTRA_OBJC, post);
                    startActivity(i);
                } else {
                    Tools.dialogCommentNeedLogin(ActivityPostDetails.this, post.url);
                }
            }
        });
        Snackbar.make(parent_view, R.string.post_detail_displayed_msg, Snackbar.LENGTH_SHORT).show();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int item_id = item.getItemId();
        if (item_id == android.R.id.home) {
            onBackPressed();
        } else if (item_id == R.id.action_share) {
            Tools.methodShare(ActivityPostDetails.this, post);
        } else if (item_id == R.id.action_later) {
            if (post.isDraft()) {
                Snackbar.make(parent_view, R.string.cannot_add_to_read_later, Snackbar.LENGTH_SHORT).show();
                return true;
            }
            String str;
            if (flag_read_later) {
                RealmController.with(this).deletePost(post.id);
                str = getString(R.string.remove_from_msg);
            } else {
                RealmController.with(this).savePost(post);
                str = getString(R.string.added_to_msg);
            }
            Snackbar.make(parent_view, "Post " + str + " Read Later", Snackbar.LENGTH_SHORT).show();
            refreshReadLaterMenu();
        } else if (item_id == R.id.action_browser) {
            Tools.directLinkToBrowser(this, post.url);
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onCreateOptionsMenu(final Menu menu) {
        getMenuInflater().inflate(R.menu.menu_activity_post_details, menu);
        read_later_menu = menu.findItem(R.id.action_later);
        refreshReadLaterMenu();
        return true;
    }

    private void dialogShowComments(List<Comment> items) {

        final Dialog dialog = new Dialog(ActivityPostDetails.this);
        dialog.setCancelable(true);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); // before
        dialog.setContentView(R.layout.dialog_comments);

        WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
        lp.copyFrom(dialog.getWindow().getAttributes());
        lp.width = WindowManager.LayoutParams.MATCH_PARENT;
        lp.height = WindowManager.LayoutParams.WRAP_CONTENT;

        RecyclerView recyclerView = (RecyclerView) dialog.findViewById(R.id.recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);
        AdapterComments mAdapter = new AdapterComments(this, items);
        recyclerView.setAdapter(mAdapter);

        ((ImageView) dialog.findViewById(R.id.img_close)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                dialog.dismiss();
            }
        });

        dialog.show();
        dialog.getWindow().setAttributes(lp);
    }

    private void refreshReadLaterMenu() {
        flag_read_later = RealmController.with(this).getPost(post.id) != null;
        Drawable drawable = read_later_menu.getIcon();
        if (flag_read_later) {
            drawable.setColorFilter(Color.BLACK, PorterDuff.Mode.SRC_ATOP);
        } else {
            drawable.setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP);
        }
    }

    private void prepareAds() {
        if (AppConfig.ENABLE_ADSENSE && NetworkCheck.isConnect(getApplicationContext())) {
            AdView mAdView = (AdView) findViewById(R.id.ad_view);
            AdRequest adRequest = new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR).build();
            // Start loading the ad in the background.
            mAdView.loadAd(adRequest);
        } else {
            ((RelativeLayout) findViewById(R.id.banner_layout)).setVisibility(View.GONE);
        }
    }

    private void showFailedView(boolean show, String message) {
        View lyt_failed = (View) findViewById(R.id.lyt_failed);
        View lyt_main_content = (View) findViewById(R.id.lyt_main_content);

        ((TextView) findViewById(R.id.failed_message)).setText(message);
        if (show) {
            lyt_main_content.setVisibility(View.GONE);
            lyt_failed.setVisibility(View.VISIBLE);
        } else {
            lyt_main_content.setVisibility(View.VISIBLE);
            lyt_failed.setVisibility(View.GONE);
        }
        ((Button) findViewById(R.id.failed_retry)).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                requestAction();
            }
        });
    }

    private void swipeProgress(final boolean show) {
        if (!show) {
            swipe_refresh.setRefreshing(show);
            return;
        }
        swipe_refresh.post(new Runnable() {
            @Override
            public void run() {
                swipe_refresh.setRefreshing(show);
            }
        });
    }

    @Override
    public void onBackPressed() {
        if(from_notif) {
            startActivity(new Intent(getApplicationContext(), ActivityMain.class));
            finish();
        } else {
            super.onBackPressed();
        }
    }
}

Logcat

12-09 13:56:43.962 6867-6914/com.balrajarpit.balrajarpit D/FA: Logging event (FE): app_exception(_ae), Bundle[{firebase_event_origin(_o)=crash, firebase_screen_class(_sc)=ActivityPostDetails, firebase_screen_id(_si)=8020478545849927104, timestamp=1512808003957, fatal=1}]
12-09 13:56:43.979 6867-6914/com.balrajarpit.balrajarpit V/FA: Connecting to remote service
12-09 13:56:43.985 6867-6914/com.balrajarpit.balrajarpit V/FA: Recording user engagement, ms: 23008
12-09 13:56:43.991 6867-6914/com.balrajarpit.balrajarpit D/FA: Logging event (FE): user_engagement(_e), Bundle[{firebase_event_origin(_o)=auto, engagement_time_msec(_et)=23008, firebase_screen_class(_sc)=ActivityPostDetails, firebase_screen_id(_si)=8020478545849927104}]
12-09 13:56:44.012 6867-6914/com.balrajarpit.balrajarpit V/FA: Connection attempt already in progress

Body:
I am not sure if it is the problem in this case, but using different versions of support libraries can cause runtime crashes. You can find the ones that use a different version (maybe used internally by another library) by executing the following command in (android studio) terminal:

gradlew -q dependencies app:dependencies --configuration compile

If the command doesn't work, you maybe have to configure a gradle wrapper first. To do so, add the following to your project build.gradle file:

task wrapper(type: Wrapper) {
    gradleVersion = '4.1'
}

and execute the command

gradle wrapper

from terminal. If it still doesn't work, gradle might not be in your PATH, you can find it in the Android Studio installation folder if you want to add it.

Once you know which one uses a different version, just add it as a dependency yourself with the correct version to override the other version and sync.

It worked for me this way when I had the problem, hope it helps!


问:
Maven 3 and JUnit 4 compilation problem: package org.junit does not exist
I am trying to build a simple Java project with Maven. In my pom-file I declare JUnit 4.8.2 as the only dependency. Still Maven insists on using JUnit version 3.8.1. How do I fix it?

The problem manifests itself in a compilation failure: "package org.junit does not exist". This is because of the import statement in my source code. The correct package name in JUnit 4.* is org.junit.* while in version 3.* it is junit.framework.*

I think I have found documentation on the root of the problem on http://maven.apache.org/plugins/maven-surefire-plugin/examples/junit.html but the advice there seems to be meant for Maven experts. I did not understand what to do.

答:
Me too had the same problem as shown below.

To resolve the issue, below lines are added to dependencies section in the app level build.gradle.

```<code>compile 'junit:junit:4.12'
androidTestCompile 'com.android.support.test:runner:0.5'
</code>```

Gradle build then reported following warning.

```<code>Warning:Conflict with dependency 'com.android.support:support-annotations'.
Resolved versions for app (25.1.0) and test app (23.1.1) differ.
See http://g.co/androidstudio/app-test-app-conflict for details.
</code>```

To solve this warning, following section is added to the app level build.gradle.

```<code>configurations.all {
    resolutionStrategy {
        force 'com.android.support:support-annotations:23.1.1'
    }
}
</code>```

Body:
Me too had the same problem as shown below.

To resolve the issue, below lines are added to dependencies section in the app level build.gradle.

compile 'junit:junit:4.12'
androidTestCompile 'com.android.support.test:runner:0.5'

Gradle build then reported following warning.

Warning:Conflict with dependency 'com.android.support:support-annotations'.
Resolved versions for app (25.1.0) and test app (23.1.1) differ.
See http://g.co/androidstudio/app-test-app-conflict for details.

To solve this warning, following section is added to the app level build.gradle.

configurations.all {
    resolutionStrategy {
        force 'com.android.support:support-annotations:23.1.1'
    }
}